CodeChef KnightMov
2017-06-10 16:21
260 查看
码死了...考试的时候基本上是写一会儿思考一会儿人生....考完了调了调...最后400行+....不应该这么长的....以后重写一下再补题解.....
也许这就是蒟蒻吧.jpg
安利cstdio博客翻译的题解.
也许这就是蒟蒻吧.jpg
安利cstdio博客翻译的题解.
#include<cstdio> #include<cstring> #include<cmath> #include<set> using namespace std; const int mod=1000000007; int X,Y,K; int ax,ay,bx,by; int xx[20],yy[20]; set<pair<int,int> > dict; double direc(int a,int b){ if(a!=0)return double(b)/a; else return 1e8; } int check1(int a,int b){ if(X==0&&Y==0)return -1; int step1,step2; if(a==0){ if(X==0){ double tmp=Y/(double)(b); if(tmp>0&&(fabs(tmp-floor(tmp))<1e-8)){ step1=tmp; int tmpx=0,tmpy=0; for(int i=1;i<=step1;++i){ tmpx+=a;tmpy+=b; if(dict.find(pair<int,int>(tmpx,tmpy))!=dict.end())return 0; } return -1; //step1=floor(tmp); }else return 0; }else return 0; }else{ step1=X/(double)(a); if(step1<=0||(fabs(step1-floor(step1))>1e-8))return 0; } if(b==0){ if(Y==0){ double tmp=X/(double)(a); if(tmp>0&&(fabs(tmp-floor(tmp))<1e-8)){ step1=tmp; int tmpx=0,tmpy=0; for(int i=1;i<=step1;++i){ tmpx+=a;tmpy+=b; if(dict.find(pair<int,int>(tmpx,tmpy))!=dict.end())return 0; } return -1; }else return 0; }else return 0; }else{ step2=Y/(double)(b); if(step2<=0||(fabs(step2-floor(step2))>1e-8))return 0; } if(step1==step2){ //blabla int tmpx=0,tmpy=0; for(int i=1;i<=step1;++i){ tmpx+=a;tmpy+=b; if(dict.find(pair<int,int>(tmpx,tmpy))!=dict.end())return 0; } return -1; } else{ return 0; } } int qpow(int a,int x){ int ans=1; for(;x;x>>=1,a=a*1ll*a%mod){ if(x&1)ans=ans*1ll*a%mod; } return ans; } int check4(int a,int b){ if(X==0&&Y==0)return -1; int step1,step2; if(a==0){ if(X==0){ double tmp=Y/(double)(b); if(tmp>0&&(fabs(tmp-floor(tmp))<1e-8)){ step1=tmp; int tmpx=0,tmpy=0; for(int i=1;i<=step1;++i){ tmpx+=a;tmpy+=b; if(dict.find(pair<int,int>(tmpx,tmpy))!=dict.end())return 0; } return 1; //step1=floor(tmp); }else return 0; }else return 0; }else{ step1=X/(double)(a); if(step1<=0||(fabs(step1-floor(step1))>1e-8))return 0; } if(b==0){ if(Y==0){ double tmp=X/(double)(a); if(tmp>0&&(fabs(tmp-floor(tmp))<1e-8)){ step1=tmp; int tmpx=0,tmpy=0; for(int i=1;i<=step1;++i){ tmpx+=a;tmpy+=b; if(dict.find(pair<int,int>(tmpx,tmpy))!=dict.end())return 0; } return 1; }else return 0; }else return 0; }else{ step2=Y/(double)(b); if(step2<=0||(fabs(step2-floor(step2))>1e-8))return 0; } if(step1==step2){ //blabla int tmpx=0,tmpy=0; for(int i=1;i<=step1;++i){ tmpx+=a;tmpy+=b; if(dict.find(pair<int,int>(tmpx,tmpy))!=dict.end())return 0; } return 1; } else{ return 0; } } int gcd(int a,int b){ return b==0?a:gcd(b,a%b); } int F[600],FF[600][600]; int seq[100],cnt=0; int BASE=250000; int q[500005]; bool dfn[500005]; bool block[500005]; bool legal(int x){ return x>=0&&x<500005; } int sum1[500005],sum2[500005]; int cir[500005],T; bool dfn2[500005]; int fff[500005]; int check3(int a,int b,int to){ b=-b; memset(cir,0,sizeof(cir)); memset(dfn,0,sizeof(dfn)); memset(block,0,sizeof(block)); memset(sum1,0,sizeof(sum1));memset(sum2,0,sizeof(sum2)); for(int i=1;i<=cnt;++i)block[seq[i]+BASE]=true; for(int i=1;i<500005;++i){ if(i>=a){ sum1[i]=sum1[i-a]+(block[i]); } else{ sum1[i]=(block[i]); } if(i>=b){ sum2[i]=sum2[i-b]+(block[i]); }else{ sum2[i]=(block[i]); } } ++T; for(int i=a*b+a+b;i<500005;++i){ if(sum1[i]-sum1[i-a*b-a]==0&&sum2[i]-sum2[i-a*b-b]==0)cir[i]=true; } int head=0,tail=0;dfn[BASE]=true; q[tail++]=BASE; while(head!=tail){ int x=q[head++]; if(legal(x+a)&&!dfn[x+a]&&!block[x+a]){ dfn[x+a]=true;q[tail++]=x+a; } if(legal(x-b)&&!dfn[x-b]&&!block[x-b]){ dfn[x-b]=true;q[tail++]=x-b; } } if(!dfn[BASE+to])return 0; memset(dfn2,0,sizeof(dfn2)); head=tail=0;dfn2[BASE+to]=true; q[tail++]=BASE+to; while(head!=tail){ int x=q[head++]; if(legal(x-a)&&!dfn2[x-a]&&!block[x-a]){ dfn2[x-a]=true;q[tail++]=x-a; } if(legal(x+b)&&!dfn2[x+b]&&!block[x+b]){ dfn2[x+b]=true;q[tail++]=x+b; } } for(int i=0;i<500005;++i){ if(cir[i]&&dfn[i]&&dfn2[i]){ return -1; } }memset(dfn,0,sizeof(dfn)); memset(fff,0,sizeof(fff));fff[BASE]=1; head=0,tail=0;dfn[BASE]=true; q[tail++]=BASE; while(head!=tail){ int x=q[head++]; if(legal(x+a)&&!dfn[x+a]&&!block[x+a]){ fff[x+a]=(fff[x+a]+fff[x])%mod; dfn[x+a]=true;q[tail++]=x+a; } if(legal(x-b)&&!dfn[x-b]&&!block[x-b]){ fff[x-b]=(fff[x-b]+fff[x])%mod; dfn[x-b]=true;q[tail++]=x-b; } } return fff[BASE+to]; } int check2(){//方向相同,可以同向,也可以反向 if(ax==0){ if(X!=0)return 0; if((ay>0)==(by>0)){ //同向 int gy=gcd(ay,by); memset(F,0,sizeof(F)); if(Y%gy!=0||Y/gy<0)return 0; int A=ay/gy,B=by/gy; F[0]=1; for(int i=0;i<=Y/gy;++i){ if(dict.find(pair<int,int>(0,gy*i))!=dict.end())F[i]=0; F[i+A]=(F[i+A]+F[i])%mod;F[i+B]=(F[i+B]+F[i])%mod; } return F[Y/gy]; }else{ //反向 int gy=gcd(fabs(ay),fabs(by)); if(Y%gy!=0)return 0; cnt=0; for(int i=1;i<=K;++i){ if(xx[i]==0&&yy[i]%gy==0){ seq[++cnt]=yy[i]/gy; } } int A=ay/gy,B=by/gy; if(A>0)return check3(A,B,Y/gy); else return check3(B,A,Y/gy); } }else if(ay==0){ if(Y!=0)return 0; if((ax>0)==(bx>0)){ //同向 int gx=gcd(ax,bx); memset(F,0,sizeof(F)); if(X%gx!=0||X/gx<0)return 0; int A=ax/gx,B=bx/gx; F[0]=1; for(int i=0;i<=X/gx;++i){ if(dict.find(pair<int,int>(gx*i,0))!=dict.end()){ F[i]=0; } F[i+A]=(F[i+A]+F[i])%mod;F[i+B]=(F[i+B]+F[i])%mod; } return F[X/gx]; }else{ //反向 int gx=gcd(fabs(ax),fabs(bx)); if(X%gx!=0)return 0; cnt=0; for(int i=1;i<=K;++i){ if(yy[i]==0&&xx[i]%gx==0){ seq[++cnt]=xx[i]/gx; } } int A=ax/gx,B=bx/gx; if(A>0)return check3(A,B,X/gx); else return check3(B,A,X/gx); } }else{ if((ax>0)==(bx>0)){ //同向 int gx=gcd(ax,bx),gy=gcd(ay,by); if(X%gx!=0||X/gx<0)return 0; if(Y%gy!=0||Y/gy<0)return 0; if(X/gx!=Y/gy)return 0; int A=ax/gx,B=bx/gx; memset(F,0,sizeof(F)); F[0]=1; F[0]=1; for(int i=0;i<=X/gx;++i){ if(dict.find(pair<int,int>(gx*i,gy*i))!=dict.end()){ F[i]=0; } F[i+A]=(F[i+A]+F[i])%mod;F[i+B]=(F[i+B]+F[i])%mod; } return F[X/gx]; }else{ //反向 int gx=gcd(fabs(ax),fabs(bx)),gy=gcd(fabs(ay),fabs(by)); if(X%gx!=0)return 0; if(Y%gy!=0)return 0; if(X/gx!=Y/gy)return 0; cnt=0; int A=ax/gx,B=bx/gx; for(int i=1;i<=K;++i){ if(yy[i]%gy==0&&xx[i]%gx==0&&yy[i]/gy==xx[i]/gx){ seq[++cnt]=xx[i]/gx; } } if(A>0)return check3(A,B,X/gx); else return check3(B,A,X/gx); } } //同向:一定无环,递推一波即可 //反向:可能有环... } int fac[500005],inv[500005]; void init(){ fac[0]=1; for(int i=1;i<500005;++i)fac[i]=fac[i-1]*1ll*i%mod; inv[0]=1; inv[1]=1; for(int i=2;i<500005;++i)inv[i]=inv[mod%i]*1ll*(mod-mod/i)%mod; for(int i=2;i<500005;++i){ inv[i]=inv[i-1]*1ll*inv[i]%mod; } } int C(int n,int m){ return fac *1ll*inv[m]%mod*inv[n-m]%mod; } int calc(int i,int j){ int dlt1=xx[j]-xx[i],dlt2=yy[j]-yy[i]; //double step1=,step2=; double step2=(dlt1*1.0*ay-dlt2*1.0*ax)/(bx*1.0*ay-by*1.0*ax); double step1=(dlt1*1.0*ay-step2*bx*ay)/ax/ay; //必然有解.无解状况已经排除. if(step1<0||step2<0)return 0; if(fabs(step1-floor(step1))>1e-8||fabs(step2-floor(step2))>1e-8)return 0; int n=step1,m=step2; return C(n+m,m); } int f[20][2];bool vis[20]; int g[20][20],deg[20]; int main(){ freopen("knightmov.in","r",stdin); freopen("knightmov.out","w",stdout); int tests;scanf("%d",&tests); init(); while(tests--){ scanf("%d%d%d",&X,&Y,&K); scanf("%d%d%d%d",&ax,&ay,&bx,&by); for(int i=1;i<=K;++i)scanf("%d%d",xx+i,yy+i); if(ax==0&&ay==0&&bx==0&&by==0){ if(X==0&Y==0){ printf("-1\n"); }else{ printf("0\n"); } continue; } dict.clear(); for(int i=1;i<=K;++i)dict.insert(pair<int,int>(xx[i],yy[i])); if(ax==bx&&ay==by){ printf("%d\n",check4(ax,ay)); } else if(ax==0&&ay==0){ printf("%d\n",check1(bx,by)); }else if(bx==0&&by==0){ printf("%d\n",check1(ax,ay)); }else{ double d1=direc(ax,ay),d2=direc(bx,by); if(d1==d2){ printf("%d\n",check2()); }else{ if(X==0&&Y==0){ printf("1\n");continue; }else{ memset(f,0,sizeof(f)); xx[0]=0;yy[0]=0;xx[K+1]=X;yy[K+1]=Y; f[0][0]=1; for(int i=1;i<=K+1;++i)vis[i]=false;vis[0]=false; memset(g,0,sizeof(g));memset(deg,0,sizeof(deg)); for(int i=0;i<=K+1;++i){ for(int j=0;j<=K+1;++j){ if(i!=j){ g[i][j]=calc(i,j); if(g[i][j])deg[j]++; } } } for(int i=0;i<=K+1;++i){ int x=0x7f7f7f7f; for(int j=0;j<=K+1;++j){ if(deg[j]==0&&!vis[j]){ x=j;break; } } if(x==0x7f7f7f7f)break; vis[x]=true; for(int t=0;t<=K+1;++t){ if(g[x][t]){ deg[t]--; f[t][1]=(f[t][1]+f[x][0]*1ll*g[x][t]%mod)%mod; f[t][0]=(f[t][0]+f[x][1]*1ll*g[x][t]%mod)%mod; } } } printf("%d\n",(f[K+1][1]-f[K+1][0]+mod)%mod); } } } } // fclose(stdin);fclose(stdout); return 0; } /* 3 3 3 0 1 2 2 1 9 9 2 1 2 2 1 1 2 6 6 1 1 0 0 0 0 0 */
相关文章推荐
- [CodeChef September Challenge 2012]Knight Moving(KNGHTMOV)题解翻译
- codechef Correctness of Knight Move题解
- CodeChef XRQRS - Xor Queries
- BZOJ4299 Codechef FRBSUM(主席树)
- Codeforces Round #207 (Div. 2) C. Knight Tournament
- CodeChef November Challenge 2013 题解
- [bzoj4299]Codechef FRBSUM
- Chef and Prime Divisors (CodeChef CHAPD
- CodeChef CHAPD
- 4260: Codechef REBXOR
- [主席树] Codechef: Prefix XOR
- codechef Partition the numbers(思维)
- [Codechef October Challenge 2014]Union on Tree(虚树+点分树)
- codechef Sums in a Triangle题解
- codechef Prime Palindromes 题解
- codechef Three Way Communications 题解
- CodeChef:Company and Club Hierarchies(树形dp & 技巧)
- codechef(MAY15)第三题Chef and Prime Divisors
- Codechef Nuclear Reactors 题解
- codechef January Lunchtime 2017简要题解