日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[SDWC2018 Day1]网格

發布時間:2024/4/11 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [SDWC2018 Day1]网格 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

學了容斥與二項式反演,也該寫寫題了

題目介紹

題目網址

題意簡介

現在有個人,要用MMM步從(0,0)(0,0)(0,0)跳到(Tx,Ty)(T_x,T_y)(Tx?,Ty?),每次只能向右上方跳(即坐標值只能加),不能在原地跳
給出一些限制:給出KKK個限制kik_iki?,表示兩個坐標不能同時加kik_iki?。給出一個數GGG,保證所有kik_iki?都是GGG的倍數,求方案數(模109+710^9+7109+7

數據范圍

Tx,Ty≤106,Mx≤Tx,My≤TyT_x,T_y\le10^6,M_x\le T_x,M_y\le T_yTx?,Ty?106,Mx?Tx?,My?Ty?
R≤1000,10000≤G≤50000,K≤50R\le 1000,10000\le G\le50000,K\le50R1000,10000G50000,K50

題解

K=0K=0K=0

先考慮K=0K=0K=0的情況
兩個維度,都是10610^6106級別的,一起做一定不好做
然后發現除了“兩維不能同時停在原地”這個限制以外,兩維是獨立的
考慮對于一維,我們已知其長度TTT以及單步最大距離MMM
求不違反規則恰好走xxx步的方案數
直接dpdpdp復雜度是Θ(TMR)\Theta(TMR)Θ(TMR)的,顯然不行
我們發現至少違反aaa次規則恰好走RRR步的方案數很好求
calc(a)calc(a)calc(a)為至少違反aaa次規則的方案數,我們發現可以選aaa步,讓這些步一開始就有M+1M+1M+1的值,那么其無論再加多少都一定是違反規則的
那么就得出calc(a)calc(a)calc(a)的式子:calc(a)=(Ra)(T?(M+1)?a+R?1R?1)calc(a)=\binom{R}{a}\binom{T-(M+1)*a+R-1}{R-1}calc(a)=(aR?)(R?1T?(M+1)?a+R?1?)
預處理組合數后計算calc(a)calc(a)calc(a)單次Θ(1)\Theta(1)Θ(1)
考慮容斥,容易發現我們要求的答案就是∑i=0R(?1)icalc(i)\sum_{i=0}^R(-1)^icalc(i)i=0R?(?1)icalc(i)
所以對于一維的答案的復雜度是Θ(R)\Theta(R)Θ(R)的,那么我們把兩維都求出來
我們發現,兩維的乘積的結果并不是我們想要的恰好RRR步,而是至多RRR
所以我們如果要合并,我們不能直接相乘
給定T,MT,MT,M,設L(R)L(R)L(R)為給至多走RRR步的方案數,E(R)E(R)E(R)為恰好走RRR步的方案數
L(R)=∑i=0R(Ri)E(i)L(R)=\sum_{i=0}^R\binom{R}{i}E(i)L(R)=i=0R?(iR?)E(i)
二項式反演
E(R)=∑i=0R(?1)R?i(Ri)L(i)E(R)=\sum_{i=0}^R(-1)^{R-i}\binom{R}{i}L(i)E(R)=i=0R?(?1)R?i(iR?)L(i)
然后發現求一次E(R)E(R)E(R)Θ(R2)\Theta(R^2)Θ(R2)的,比較優越

K≠0K\neq0K??=0

然后我們考慮有KKK限制的情況
我們發現我們要求的是不違反限制的情況,但是并不好求
又發現,至少違反nnn次數的情況很好統計
同樣考慮容斥,g(x)g(x)g(x)為至少違反xxx次的方案數,容易發現我們要求的就是∑i=0∞(?1)ig(i)\sum_{i=0}^{\infty}(-1)^ig(i)i=0?(?1)ig(i)
我們先來思考iii的范圍,由于kik_iki?都是GGG的倍數,而G≥10000G\ge10000G10000,所以iii的取值范圍是Θ(TG)=Θ(100)\Theta(\frac TG)=\Theta(100)Θ(GT?)=Θ(100)
考慮dpdpdp來統計ggg,定義fi,jf_{i,j}fi,j?為至少違反jjj次、∑k=j?G\sum k=j*Gk=j?G的方案數,容易發現第二維也是Θ(100)\Theta(100)Θ(100)
fi,jf_{i,j}fi,j?對答案的貢獻系數即Tx?j?G,Ty?j?G,x?iT_x-j*G,T_y-j*G,x-iTx??j?G,Ty??j?G,x?i步并且沒有任何限制的答案,通過前面K=0K=0K=0的部分的分析可以得知這部分的復雜度是Θ(Mx)\Theta(Mx)Θ(Mx)的,總復雜度大概是Θ(1000?1000?100?100)\Theta(1000*1000*100*100)Θ(1000?1000?100?100)
貌似能過??而且跑的飛快
當然我們要科學的復雜度,只要預處理L(x)L(x)L(x)即可,我們發現TTT的取值因為jjj的不同只有Θ(100)\Theta(100)Θ(100)組,步數是Θ(R)\Theta(R)Θ(R)的,一次處理是Θ(R)\Theta(R)Θ(R)
所以總復雜度為Θ(TGR2)\Theta(\frac TGR^2)Θ(GT?R2)大約10810^8108左右,再加上根本跑不滿,所以很容易就過了

代碼

#include<cstdio> #include<cctype> #include<algorithm> namespace fast_IO {const int IN_LEN=10000000,OUT_LEN=10000000;char ibuf[IN_LEN],obuf[OUT_LEN],*ih=ibuf+IN_LEN,*oh=obuf,*lastin=ibuf+IN_LEN,*lastout=obuf+OUT_LEN-1;inline char getchar_(){return (ih==lastin)&&(lastin=(ih=ibuf)+fread(ibuf,1,IN_LEN,stdin),ih==lastin)?EOF:*ih++;}inline void putchar_(const char x){if(oh==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf;*oh++=x;}inline void flush(){fwrite(obuf,1,oh-obuf,stdout);} } using namespace fast_IO; #define getchar() getchar_() #define putchar(x) putchar_((x)) //#include<ctime> #define rg register typedef long long LL; template <typename T> inline T max(const T a,const T b){return a>b?a:b;} template <typename T> inline T min(const T a,const T b){return a<b?a:b;} template <typename T> inline void mind(T&a,const T b){a=a<b?a:b;} template <typename T> inline void maxd(T&a,const T b){a=a>b?a:b;} template <typename T> inline T abs(const T a){return a>0?a:-a;} template <typename T> inline void swap(T&a,T&b){T c=a;a=b;b=c;} //template <typename T> inline void swap(T*a,T*b){T c=a;a=b;b=c;} template <typename T> inline T gcd(const T a,const T b){if(!b)return a;return gcd(b,a%b);} template <typename T> inline T lcm(const T a,const T b){return a/gcd(a,b)*b;} template <typename T> inline T square(const T x){return x*x;}; template <typename T> inline void read(T&x) {char cu=getchar();x=0;bool fla=0;while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}while(isdigit(cu))x=x*10+cu-'0',cu=getchar();if(fla)x=-x; } template <typename T> inline void printe(const T x) {if(x>=10)printe(x/10);putchar(x%10+'0'); } template <typename T> inline void print(const T x) {if(x<0)putchar('-'),printe(-x);else printe(x); } const LL mod=1000000007; inline void md(LL&x){if(x>=mod)x-=mod;} LL fac[1000001],inv[1000001]; inline LL pow(LL x,LL y) {LL res=1;for(;y;y>>=1,x=x*x%mod)if(y&1)res=res*x%mod;return res; } inline LL C(LL x,LL y){return fac[x]*inv[y]%mod*inv[x-y]%mod;} inline void init() {fac[0]=1;for(rg int i=1;i<=1000000;i++)fac[i]=fac[i-1]*i%mod;inv[1000000]=pow(fac[1000000],mod-2);for(rg int i=1000000;i>=1;i--)inv[i-1]=inv[i]*i%mod; } int T,Tx,Ty,Mx,My,R,G; int K,k[51]; LL f[101][101],g[101]; LL calc[101][1001]; inline LL solve(const int x,const int step) {LL res=0;for(rg int i=0;i<=step;i++){if((i&1)==(step&1))md(res+=calc[x][i]*C(step,i)%mod);else md(res+=mod-calc[x][i]*C(step,i)%mod);}return res; } int main() {init();read(Tx),read(Ty),T=min(Tx,Ty),read(Mx),read(My),read(R),read(G);for(rg int i=0;G*i<=T;i++){const int tx=Tx-G*i,ty=Ty-G*i;for(rg int j=R;j>=0;j--){if(j*Mx<tx||j*My<ty)break;LL valx=0,valy=0;for(rg int step=0;step<=j&&(Mx+1)*step<=tx;step++)if(step&1)md(valx+=mod-C(j,step)*C(tx-(Mx+1)*step+j-1,j-1)%mod);else md(valx+=C(j,step)*C(tx-(Mx+1)*step+j-1,j-1)%mod);for(rg int step=0;step<=j&&(My+1)*step<=ty;step++)if(step&1)md(valy+=mod-C(j,step)*C(ty-(My+1)*step+j-1,j-1)%mod);else md(valy+=C(j,step)*C(ty-(My+1)*step+j-1,j-1)%mod);calc[i][j]=valx*valy%mod;}}read(K);for(rg int i=1;i<=K;i++)read(k[i]);std::sort(k+1,k+K+1);K=std::unique(k+1,k+K+1)-k-1;for(rg int i=1;i<=K;i++)k[i]/=G;f[0][0]=1,g[0]=solve(0,R);for(rg int i=1;G*i<=T;i++)for(rg int j=0;G*j<=T;j++){for(rg int kind=1;kind<=K;kind++)if(k[kind]<=j)md(f[i][j]+=f[i-1][j-k[kind]]);md(g[i]+=solve(j,R-i)*f[i][j]%mod);}LL ans=0;for(rg int i=0;G*i<=T;i++)if(i&1)md(ans+=mod-g[i]*C(R,i)%mod);else md(ans+=g[i]*C(R,i)%mod);print(ans);return flush(),0; }

總結

這道題的非常巧妙,多次運用容斥與反演的技巧,值得深思
致謝:感謝yx2003在本題上對我的指導

總結

以上是生活随笔為你收集整理的[SDWC2018 Day1]网格的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。