「CF1227F2」題解
阿新 • • 發佈:2021-11-27
Description
CF1227F2 Wrong Answer on test 233 (Hard Version)
題目大意就是給定一個序列 \(h\),問有多少序列 \(a\),滿足 \(a\) 與 \(h\) 的相似度小於 \(a\) 與 \(h\) 左移後的相似度。
或者你叫漢明距離也行。
稱左移後的 \(h\) 為 \(h'\)。
容易想到若 \(a_i=h_i\) 這一位無論取多少都不影響最終結果,假設有 \(tot\) 個這樣的位置,這部分的貢獻就是 \(m^{tot}\)。
先將 \(n\) 減去 \(tot\)。
否則假設剩下位置中 \(a\) 個位置為與 \(h_i\)
則 \[ans=\sum_{a=1}^{n}\sum_{b=0}^{a-1}\binom{n}{a}\binom{n-a}{b}(m-2)^{n-a-b} \]
預處理 \(m-2\) 的次方後時間複雜度 \(\Theta(n^2)\),可過簡單版。
考慮化簡式子。
列舉 \(a+b\)
就沒了。
時間複雜度 \(\Theta(n)\)(我沒預處理,帶個 \(\log\))
Code:
#include<cstdio> #include<algorithm> #include<iostream> using namespace std; const int MAXM=4e5+5; const int M=4e5; const int Mod=998244353; #define ll long long int n,m,a[MAXM],tot; ll fra[MAXM],ofra[MAXM],Ans,doo; ll ksm(ll a,int b){ ll ans=1; while(b){ if(b&1) ans=ans*a%Mod; a=a*a%Mod;b>>=1; } return ans; } ll C(int n,int k){ if(k>n) return 0; return (fra[n]*ofra[k]%Mod)*ofra[n-k]%Mod; } int main(){ fra[0]=1; for(int i=1;i<=M;i++){ fra[i]=fra[i-1]*i%Mod; } ofra[M]=ksm(fra[M],Mod-2); for(int i=M;i;i--){ ofra[i-1]=ofra[i]*i%Mod; } scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } for(int i=1;i<=n;i++){ if(a[i]==a[i%n+1]) tot++; } doo=ksm(m,tot); n-=tot; for(int i=1;i<=n;i++){ ll tmp=ksm(2,i); if(i%2==0){ tmp=(((tmp-C(i,i/2))%Mod)+Mod)%Mod; } tmp=tmp*ksm(2,Mod-2)%Mod; tmp=tmp*C(n,i)%Mod; Ans=(Ans+ksm(m-2,n-i)*tmp)%Mod; } printf("%lld\n",Ans*doo%Mod); return 0; }