CF1151F Sonya and Informatics(dp+矩阵快速幂)
这题设计二维状态f[][]表示前i个里面有几个0,假设数列中总共有cnt个0最后答案就是操作k次后前i个里面有cnt个0/所有情况
因为k十分巨大,所以考虑使用矩阵快速幂加速dp
对于矩阵状态的设计,就是看看转移状态,发现转移状态只是一个常数,因此列出矩阵后做一遍快速幂即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define getsz(p) (p?p->sz:0) using namespace std; typedef long long ll; const int mod=1e9+7; const int N=200; int pow_mod(int x,int i) { int res=1; while(i){ if(i&1) res=(ll)res*x%mod; x=(ll)x*x%mod; i>>=1; } return res; } int n,k,a[N]; int cnt; struct node{ int a[N][N]; node(){memset(a,0,sizeof(a));} }s,t; node operator *(node a,node b) { node tmp; for(int i=0;i<=cnt;i++) { for(int j=0;j<=cnt;j++) { for(int k=0;k<=cnt;k++) { tmp.a[i][j]=((ll)tmp.a[i][j]+(ll)a.a[i][k]*b.a[k][j]%mod)%mod; } } } return tmp; } node matrix_pow(node a,int i) { node b; for(int i=0;i<=cnt;i++) b.a[i][i]=1; while(i) { if(i&1) b=b*a; a=a*a; i>>=1; } return b; } int main() { ios::sync_with_stdio(false); cin>>n>>k; for(int i=1;i<=n;i++) cin>>a[i],cnt+=(a[i]==0); int num=0; for(int i=1;i<=cnt;i++) num+=(a[i]==0); s.a[0][num]=1; for(int i=0;i<=cnt;i++) { if(i!=0) t.a[i-1][i]=1ll*(cnt-(i-1))*(cnt-(i-1))%mod; t.a[i][i]=1ll*(1ll*i*(cnt-i)%mod+1ll*(cnt-i)*(n-cnt-cnt+i))%mod; t.a[i][i]=(t.a[i][i]+1ll*cnt*(cnt-1)/2%mod)%mod; t.a[i][i]=(t.a[i][i]+1ll*(n-cnt)*(n-cnt-1)/2%mod)%mod; if(i!=cnt) t.a[i+1][i]=1ll*(i+1)*(n-cnt-cnt+i+1)%mod; } t=matrix_pow(t,k); s=s*t; int ans=s.a[0][cnt]; int tot=0; for(int i=0;i<=cnt;i++) tot=((ll)tot+s.a[0][i])%mod; ans=((ll)ans*pow_mod(tot,mod-2))%mod; cout<<ans<<endl; return 0; }
没有人不辛苦,只有人不喊疼