PE427 n-sequences
n-sequences
對於⼀個序列\(S\),令\(L(S)\)表示\(S\)中最長的值相同的子串的⻓度。
令\(f(n)\)表示對於所有\(n^n\)個長度為\(n\)的每個數值都在\(1\)到\(n\)之間序列的\(L\)值總和。
求\(f(7.5e6)\)。
題解
⾸先轉化為求\(L(S)\geq 1, L(S)\geq 2, …\)的方案然後相加。
接著補集轉化為\(L(S)\leq k\)的方案,也就是每段都不超過\(k\)的方案。
設\(g(i)\)表示滿足條件的長度為\(i\)的序列的種數,有\(g(0)=1\)。
-
當\(1\leq i\leq k\)時,\(g(i)=n\times g(i-1)\)
-
當\(i=k+1\)時,恰好有\(n\)種方案不合法,\(g(i)=n\times g(i-1)-n\times g(0)\)。
-
當\(k+2\leq i\leq n\)時,容斥掉\(i-k\sim i\)都是同色的的方案。那麼由於\(g(i-1)\)的限制,\(i-k-1\)和\(i-k\)的顏色必須不同。所以\(g(i)=n\times g(i-1)-(n-1)\times g(i-k-1)\)。
直接計算的話時間複雜度\(O(n^2)\)不可取。
CO int N=100; int64 g[N]; int main(){ int n=11; int64 pwr=pow(n,n),ans=0; for(int k=0;k<n;++k){ g[0]=1; for(int i=1;i<=k;++i) g[i]=n*g[i-1]; g[k+1]=n*g[k]-n*g[0]; for(int i=k+2;i<=n;++i) g[i]=n*g[i-1]-(n-1)*g[i-k-1]; ans+=pwr-g[n]; } printf("%lld\n",ans); return 0; }
假設沒有第2種轉移,考慮這個遞推式的組合意義。相當於走樓梯,往上走\(1\)步的代價是乘\(n\),走\(k+1\)步的代價是乘\(-(n-1)\)。
那麼我們列舉一共做了多少次走\(k+1\)步
\[\sum_{i(k+1)\leq n}n^{n-i(k+1)}(1-n)^{i}\binom{n-i(k+1)+i}{i} \]
第二種轉移無非是列舉第一次的決策拆開來計算
\[\sum_{i(k+1)\leq n}(n^{n-i(k+1)}(1-n)^{i}\binom{n-i(k+1)-1+i}{i}-n^{n-i(k+1)+1}(1-n)^{i-1}\binom{n-i(k+1)+i-1}{i-1}) \]
時間複雜度調和級數\(O(n\ln n)\)。
CO int N=1e7;
int fac[N],ifac[N];
int pn[N],p1n[N];
IN int C(int n,int m){
if(n<m) return 0;
return mul(fac[n],mul(ifac[m],ifac[n-m]));
}
int main(){
int n=7.5e6;
fac[0]=1;
for(int i=1;i<=n;++i) fac[i]=mul(fac[i-1],i);
ifac[n]=fpow(fac[n],mod-2);
for(int i=n-1;i>=0;--i) ifac[i]=mul(ifac[i+1],i+1);
pn[0]=p1n[0]=1;
for(int i=1;i<=n;++i){
pn[i]=mul(pn[i-1],n);
p1n[i]=mul(p1n[i-1],1+mod-n);
}
int ans=0;
for(int k=0;k<n;++k){
if(k==0){
ans=add(ans,pn[n]);
continue;
}
int sum=0;
for(int i=0;i*(k+1)<=n;++i){
if(i==0){
sum=add(sum,pn[n]);
continue;
}
sum=add(sum,mul(pn[n-i*(k+1)],mul(p1n[i],C(n-i*(k+1)-1+i,i))));
sum=add(sum,mod-mul(pn[n-i*(k+1)+1],mul(p1n[i-1],C(n-i*(k+1)+i-1,i-1))));
}
ans=add(ans,add(pn[n],mod-sum));
}
printf("%d\n",ans);
return 0;
}