链接
https://ac.nowcoder.com/acm/contest/879/A
题意
完全图中从 点 $1$ 出发,经过 $k$ 条边(可重复)回到点 $1$ 的方案数。
思路一
设矩阵 $A$ 中每个元素都为 $1$,矩阵 $I$ 为单位矩阵,
所以根据题意,我们要求的就是 $(A-I)^k_{0,0}$。
根据矩阵二项式定理:$(A-I)^k=\sum_{i=0}^{k}\binom{k}{i}A^i(-1)^{k-i}$。
所以
$\begin{aligned}
(A-I)^k_{0,0} &=\sum_{i=0}^{k}\binom{k}{i}n^{\max(0,i-1)}(-1)^{k-i}\
&=\sum_{i=0}^{k}\binom{k}{i}\frac{n^{\max(1,i)}}{n}(-1)^{k-i}\
&=\frac{1}{n}((n-1)^k-\binom{k}{0}n^{0}(-1)^{k}+\binom{k}{0}n^{1}(-1)^{k})\
&=\frac{(n-1)^k+(-1)^k(n-1)}{n}\
\end{aligned}$
代码一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| #include <bits/stdc++.h> #define SZ(x) (int)(x).size() #define ALL(x) (x).begin(),(x).end() #define PB push_back #define EB emplace_back #define MP make_pair #define FI first #define SE second using namespace std; typedef double DB; typedef long double LD; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; typedef vector<int> VI; typedef vector<PII> VPII;
const int MOD=998244353; LL n,k; LL qpow(LL a,LL b) { LL ret=1; while(b) { if(b&1) ret=ret*a%MOD; a=a*a%MOD; b>>=1; } return ret; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin>>n>>k; cout<<(qpow(n-1,k)+(n-1)*(k&1?-1:1)+MOD)%MOD*qpow(n,MOD-2)%MOD<<'\n'; return 0; }
|
思路二
记 $dp_{i,1}$ 为经过 $i$ 条边在点 $1$ 的方案数,$dp_{i,0}$ 为经过 $i$ 条边不在点 $1$ 的方案数。
转移方程:
$\begin{cases}
dp[i][1]=dp[i-1][0]\
dp[i][0]=(n-1)dp[i-1][1]+(n-2)dp[i-1][0]
\end{cases}$
构造矩阵加速递推。
代码二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| #include <bits/stdc++.h> #define SZ(x) (int)(x).size() #define ALL(x) (x).begin(),(x).end() #define PB push_back #define EB emplace_back #define MP make_pair #define FI first #define SE second using namespace std; typedef double DB; typedef long double LD; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; typedef vector<int> VI; typedef vector<PII> VPII;
const LL MOD=998244353; int sz; struct M { LL a[105][105]; void clear() {memset(a,0,sizeof a);} M() {clear();} void init() { clear(); for(int i=0;i<sz;i++) a[i][i]=1; } M operator + (const M &T) const { M ret; for(int i=0;i<sz;i++) for(int j=0;j<sz;j++) ret.a[i][j]=(a[i][j]+T.a[i][j])%MOD; return ret; } M operator - (const M &T) const { M ret; for(int i=0;i<sz;i++) for(int j=0;j<sz;j++) ret.a[i][j]=(a[i][j]-T.a[i][j]+MOD)%MOD; return ret; } M operator * (const LL &v) const { M ret; for(int i=0;i<sz;i++) for(int j=0;j<sz;j++) { if(!a[i][j]) continue; ret.a[i][j]=a[i][j]*v%MOD; } return ret; } M operator * (const M &T) const { M ret; for(int i=0;i<sz;i++) for(int k=0;k<sz;k++) { LL t=a[i][k]; if(!t) continue; for(int j=0;j<sz;j++) { if(!T.a[k][j]) continue; ret.a[i][j]=(ret.a[i][j]+T.a[k][j]*t%MOD)%MOD; } } return ret; } M operator ^ (LL b) const { M ret,bas; for(int i=0;i<sz;i++) ret.a[i][i]=1; for(int i=0;i<sz;i++) for(int j=0;j<sz;j++) bas.a[i][j]=a[i][j]; while(b) { if(b&1) ret=ret*bas; bas=bas*bas; b>>=1; } return ret; } void print() { for(int i=0;i<sz;i++) for(int j=0;j<sz;j++) cout<<a[i][j]<<" \n"[j==sz-1]; } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); LL n,k; cin>>n>>k; sz=2; M t1,t2; t1.a[0][0]=1; t2.a[1][0]=1,t2.a[0][1]=n-1,t2.a[1][1]=n-2; t1*=t2^k; cout<<t1.a[0][0]<<'\n'; return 0; }
|