• CodeChef KnightMov


    码死了...考试的时候基本上是写一会儿思考一会儿人生....考完了调了调...最后400行+....不应该这么长的....以后重写一下再补题解.....

    也许这就是蒟蒻吧.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[n]*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
    ");
          }else{
    	printf("0
    ");
          }
          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
    ",check4(ax,ay));
        }
        else if(ax==0&&ay==0){
          printf("%d
    ",check1(bx,by));
        }else if(bx==0&&by==0){
          printf("%d
    ",check1(ax,ay));
        }else{
          double d1=direc(ax,ay),d2=direc(bx,by);
          if(d1==d2){
    	printf("%d
    ",check2());
          }else{
    	if(X==0&&Y==0){
    	  printf("1
    ");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
    ",(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
    
    */
    
    
  • 相关阅读:
    [APIO2016]划艇
    C# 循环的判断会进来几次
    C# 性能分析 反射 VS 配置文件 VS 预编译
    C# 性能分析 反射 VS 配置文件 VS 预编译
    AutoHotKey 用打码的快捷键
    AutoHotKey 用打码的快捷键
    C# 通过编程的方法在桌面创建回收站快捷方式
    C# 通过编程的方法在桌面创建回收站快捷方式
    C# 条件编译
    C# 条件编译
  • 原文地址:https://www.cnblogs.com/liu-runda/p/6979099.html
Copyright © 2020-2023  润新知