P2012-拯救世界2【EGF】
阿新 • • 發佈:2021-06-21
正題
題目連結:https://www.luogu.com.cn/problem/P2012
題目大意
\(12\)種東西排列成長度為\(n\)的序列,要求前四種出現奇數次,後四種出現偶數次,求方案。\(T\)組資料,對\(10^9\)取模。
\(1\leq n< 2^{63},1\leq T\leq 2\times 10^5\)
解題思路
顯然是\(EGF\),沒有限制的話就是\(e^x\),奇數就是\(\frac{e^x-e^{-x}}{2}\),偶數就是\(\frac{e^{x}+e^{-x}}{2}\),這些都是老生常談了。
然後答案就是
\[n!\times (\frac{e^x-e^{-x}}{2})^4(\frac{e^x+e^{-x}}{2})^4(e^{x})^4 \]然後解出來就是
然後發現\(256\)沒有逆元,但是因為這些底數都含有\(256\)的因數\(2\)所以
\[=81\times 12^{n-4}-8^{n-2}+6\times 4^{n}-4+(-4)^{n-4} \]小的直接處理就好了
然後發現這樣還是過不了,那就用擴充套件尤拉定理模上一個\(\varphi(10^9)=4\times 10^8\)
時間複雜度\(O(20000+T)\)
code
#include<cstdio> #include<cstring> #include<algorithm> #include<cctype> #define ll long long using namespace std; const ll b[5]={0,0,0,0,24},T=20000,N=T+10,P=1e9,Phi=4e8; ll n,pw2[N],pw3[N],Pw2[N],Pw3[N]; ll read(){ ll x=0,f=1;char c=getchar(); while(!isdigit(c)){if(c=='-')f=-f;c=getchar();} while(isdigit(c))x=(x<<1)+(x<<3)+c-48,c=getchar(); return x*f; } void print(ll x) {if(x>9)print(x/10);putchar(x%10+48);return;} ll G4(ll n) {n%=Phi;return Pw2[n/T]*Pw2[n/T]%P*pw2[n%T]%P*pw2[n%T]%P;} ll G8(ll n) {n%=Phi;return Pw2[n/T]*pw2[n%T]%P*G4(n)%P;} ll G12(ll n) {n%=Phi;return Pw3[n/T]*pw3[n%T]%P*G4(n)%P;} signed main() { pw2[0]=pw3[0]=Pw2[0]=Pw3[0]=1; for(ll i=1;i<=T;i++) pw2[i]=pw2[i-1]*2ll%P,pw3[i]=pw3[i-1]*3ll%P; for(ll i=1;i<T;i++) Pw2[i]=Pw2[i-1]*pw2[T]%P,Pw3[i]=Pw3[i-1]*pw3[T]%P; while(1){ n=read(); if(!n)break; if(n<=4){print(b[n]),putchar('\n');continue;} ll ans=81ll*G12(n-4); ans=ans-G8(n-2); ans=ans+6ll*G4(n-4); ans=ans+((n&1)?-1:1)*G4(n-4); print((ans%P+P)%P); putchar('\n'); } return 0; }