0、T1现场推模板,浪费大量时间,导致T2时间不足,公式推错。T2不会Crt。
总体节奏稍慢。gcd推导过程混乱。应减少时间损耗。
1、方程的解:exgcd。背模板。理解模板。
skyh等人:a,b>0时,公式最值做差。a||b<0,一堆特判。
我:先把x抬到>=1,y伴随变换,再把y降到>=1,记录差值。
优点:不用很多特判。
失误:未考虑无限解。应加特判:a,b异号。a,b同号时负相关。异号正相关,同升同降。
考虑多种情况,多手模几个点,覆盖所有情况、范围。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define F(i,a,b) for(register int i=a;i<=b;i++) 5 #define pf(a) printf("%d ",a) 6 #define phn printf(" ") 7 #define LL long long 8 #define il inline 9 #define cst const 10 #define rg register 11 using namespace std; 12 #define int long long 13 int read(); 14 int a,b,c; 15 const int MX=65535; 16 il void prtf(cst int x){if(x<=0){puts("0");return ;} if(x<=MX)printf("%lld ",x);else puts("ZenMeZheMeDuo");} 17 int exgcd(int a,int b,int &x,int &y){ 18 if(b==0){ 19 x=1;y=0;return a; 20 } 21 int d=exgcd(b,a%b,x,y); 22 int t=x;x=y; 23 y=t-a/b*x; 24 return d; 25 } 26 //不合法 27 main(){ 28 int T=read(); 29 while(T--){ 30 a=read();b=read();c=read(); 31 if(a+b==c){ 32 puts("1"); 33 } 34 else if(a==1&&b==1){ 35 if(c>=2)prtf(c-1); 36 else puts("0"); 37 } 38 else if(a==0||b==0){ 39 if(a==0&&b==0){ 40 if(c==0)prtf(70000); 41 else puts("0"); 42 } 43 else { 44 LL x=a+b; 45 if(x*c>0){ 46 if(c%x!=0)puts("0"); 47 else prtf(70000); 48 } 49 else puts("0"); 50 } 51 continue; 52 } 53 else{ 54 int x=0,y=0; 55 int d=exgcd(a,b,x,y); 56 if(c%d!=0){ 57 puts("0");continue; 58 } 59 if(c==0){ 60 if(1ll*a*b>0)puts("0"); 61 else prtf(70000); 62 continue; 63 } 64 if(1ll*a*b<0){ 65 puts("ZenMeZheMeDuo");continue; 66 } 67 int k1=b/d,k2=a/d,p=0; 68 x*=(c/d);y*=(c/d); 69 p=(1-x)/k1;x+=p*k1;if(x<1)x+=k1,p++; 70 y-=p*k2; 71 if(y<1){ 72 puts("0");continue; 73 } 74 p=(1-y)/k2;y+=p*k2;if(y<1)y+=k2,p++; 75 // printf("%d %d %d %d %d ",x,y,p,k1,k2); 76 prtf((-p)+1); 77 } 78 } 79 } 80 il int read(){ 81 rg int s=0,f=0;rg char ch=getchar(); 82 while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();} 83 while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+(ch^48);ch=getchar();} 84 return f?-s:s; 85 } 86 /* 87 g++ 1.cpp -g 88 ./a.out 89 3 90 1 0 3 91 1 1 65536 92 1 2 65537999 93 */
2、数论模板题。没学exlux,公式推对时间不够用。实际10分,有时间公式改对30分,加P质数特判 理论最大60分。
特判部分分。分析复杂度。对复杂度估计不足,没想到会T,而且特判可多得分。
inv(i)=inv(i+1)*i%p不能适用所有范围。模数较小时最后一项为0,递推前面所有为零。
解决:1、只求%pi阶乘,逆元qpow求。 2、边界min(n,p[i]-1)。
该看代码看代码,想不出来空耗时间。这些东西都相当于板子,用过就会了。
知识如果别人提前学了自己也要跟上,即使少打点题,即使看题解。
组合数部分:决策分类。四个方向移动。有效决策(步数)是哪些。其余怎么走。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #define F(i,a,b) for(register int i=a;i<=b;++i) 6 #define pf(a) printf("%d ",a) 7 #define PF(a) printf("%lld ",a) 8 #define phn printf(" ") 9 #define LL long long 10 #define il inline 11 #define cst const 12 #define rg register 13 using namespace std; 14 int read(); 15 int n,m,MOD; 16 LL jc[100010][30],Inv[100010][30]; 17 il LL exgcd(LL a,LL b,LL &x,LL &y){ 18 if(b==0){ 19 x=1;y=0;return a; 20 } 21 LL d=exgcd(b,a%b,x,y); 22 LL t=x;x=y; 23 y=t-a/b*y; 24 return d; 25 } 26 il LL inv(LL a,LL mod){ 27 LL x,y; 28 LL d=exgcd(a,mod,x,y); 29 if(d!=1)return -1; 30 return (x%mod+mod)%mod; 31 } 32 il LL qpow(rg LL x,int k,cst int mod){ 33 rg LL s=1; 34 while(k){ 35 if(k&1)s=s*x%mod; 36 x=x*x%mod;k>>=1; 37 } 38 return s; 39 } 40 int a[30],res[30],tot; 41 il LL C(LL x,LL y,cst int j){ 42 if(x<y||x<0||y<0)return 0; 43 if(x==y||y==0)return 1; 44 return jc[x][j]*qpow(jc[y][j],a[j]-2,a[j])%a[j]*qpow(jc[x-y][j],a[j]-2,a[j])%a[j]; 45 } 46 /* 47 il LL power(LL x,LL k,int mod){ 48 LL s=0; 49 while(k){ 50 if(k&1)s=(s+x)%mod; 51 x=(x+x)%mod;k>>=1; 52 } 53 return s; 54 }*/ 55 il LL Crt(){ 56 rg LL M=MOD; 57 LL sum=0; 58 F(i,1,tot){ 59 LL D=M/a[i]; 60 LL t,y; 61 exgcd(D,a[i],t,y); 62 sum=(sum+res[i]*D%M*t%M+M)%M; 63 } 64 return (sum+M)%M; 65 } 66 il LL lux(LL x,LL y,int j){ 67 if(y==0)return 1; 68 return C(x%a[j],y%a[j],j)*lux(x/a[j],y/a[j],j)%a[j]; 69 } 70 int main(){ 71 int T=read();const int mod=read();MOD=mod; 72 n=read();m=read(); 73 if(n<0)n=-n;if(m<0)m=-m; 74 if((n+m>T)||((T-n-m)%2==1)){ 75 puts("0");return 0; 76 } 77 int x=mod; 78 // F(j,1,cnt)if((x%prm[j])==0){a[++tot]=prm[j];x/=prm[j];} 79 const int end=sqrt(x); 80 F(i,2,end)if(x%i==0){a[++tot]=i;x/=i;} 81 if(x>1)a[++tot]=x;//pf(tot);pf(a[tot]);phn; 82 F(j,1,tot)jc[0][j]=1; 83 F(j,1,tot){ 84 F(i,1,T)jc[i][j]=jc[i-1][j]*i%a[j]; 85 } 86 // pf(8848);phn; 87 LL ans=0,s=1,w=1; 88 int k=T-n-m; 89 for(int i=0;i<=k;i+=2){ 90 F(j,1,tot){ 91 res[j]=(res[j]+lux(T,i>>1,j)*lux(T-(i>>1),n+(i>>1),j)%a[j]*lux(T-n-i,(k-i)>>1,j)%a[j])%a[j]; 92 } 93 } 94 printf("%lld",Crt()); 95 } 96 il int read(){ 97 rg int s=0,f=0;rg char ch=getchar(); 98 while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();} 99 while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+(ch^48);ch=getchar();} 100 return f?-s:s; 101 } 102 /* 103 g++ 6.cpp -g 104 ./a.out 105 12 1000000007 106 2 2 107 */
3、光:
60分开数组小模拟。100分数组只记录障碍大模拟。
60分小细节:1、0,n+1,m+1边界转为障碍,避免特判。
2、const int a={1,1,-1,-1}......
3、原路反弹直接跳回起点减少时间。
70分(10分cout n*m):
特判cout可以无形中多拿部分分。
搜索思路:
数组记录障碍、经过状态。
边界设为障碍省得特判。
递归:退出条件,ans统计,
下层转移方向:1、无障碍 2、有障碍:障碍状态。
#include<cstdio> #include<iostream> #include<cstring> #define F(i,a,b) for(register int i=a;i<=b;i++) #define pf(a) printf("%d ",a) #define phn printf(" ") #define LL long long #define il inline #define cst const #define rg register using namespace std; int read(); int n,m,k,sx,sy; bool a[1003][1003]; bool c[1003][1003][4]; bool vis[1003][1003]; int X[6]={1,-1,1,-1},Y[6]={1,1,-1,-1}; int sum,las; void dfs(const rg int x,const rg int y,const rg int p){ if(!vis[x][y]){ vis[x][y]=1;sum++; } else if(c[x][y][p]){ return ; } c[x][y][p]=1; if(!a[x+X[p]][y+Y[p]]){ dfs(x+X[p],y+Y[p],p); } else { const int tx=x+X[p],ty=y+Y[p]; if(a[tx][y]==1&&a[x][ty]==0){ F(i,0,3)if((X[i]==x-tx)&&(Y[i]==Y[p])){dfs(x,ty,i);break;} } else if(a[tx][y]==0&&a[x][ty]==1){ F(i,0,3)if((X[i]==X[p])&&(Y[i]==y-ty)){dfs(tx,y,i);break;} } else { las=3-las; dfs(sx,sy,las); } } } void work1(){ int x,y; F(i,1,k){x=read();y=read();a[x][y]=1;} sx=read();sy=read(); char str[3];scanf("%s",str); if(str[0]=='N')x=-1;else x=1; if(str[1]=='E')y=1;else y=-1; F(i,0,m+1)a[0][i]=a[n+1][i]=1; F(i,0,n+1)a[i][0]=a[i][m+1]=1; int p=0; F(i,0,3)if(x==X[i]&&y==Y[i]){p=i;break;} las=p; dfs(sx,sy,p); printf("%d ",sum); } int main(){ n=read();m=read();k=read(); if(n<=1000&&m<=1000)work1(); else printf("%lld",1ll*n*m); } il int read(){ int s=0,f=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();} while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+(ch^48);ch=getchar();} return f?-s:s; } /* g++ 3.cpp -g ./a.out 3 3 0 2 2 SE */
100分:
哪些是必要的,哪些可以忽视,或暂时忽视。
忽视不必要的从而增大整体效益。奥卡母剃刀。
自律。
解析几何性质。二分。
#include<cstdio> #include<iostream> #include<cstring> #include<vector> #include<algorithm> #include<map> #define F(i,a,b) for(register int i=a;i<=b;i++) #define pf(a) printf("%d ",a) #define phn printf(" ") #define LL long long #define il inline #define cst const #define rg register using namespace std; int read(); int n,m,k,sx,sy; LL ans;int cishu,org,secs,fanhui; #define NX 200300 map<pair<int,int>,bool >ditu; vector<int>q1[NX<<1],q2[NX<<1];//q1:/差,q2:和. #define mp(a,b) make_pair(a,b) int tot; void dfs(int x,int y,int d){ // printf("%d %d %d: ",x,y,d); // tot++; // if(tot==8){ // while(1); // } if(secs){ return ; } if(d==1){ int w=x-y+m+1; int va=(*upper_bound(q1[w].begin(),q1[w].end(),x))-1,vb; vb=va-w+m+1; // printf("%d %d ",va,vb); //if(va==4&&vb==2){ // printf("%d %d ",x,y);while(1); //} if(org==d&&sx-sy+m+1==w&&sx>=x&&sx<=va){ cishu++; // pf(8848);phn; if(cishu!=1){ ans+=abs(sx-x);secs=1;return ; } } ans+=abs(va-x)+1; int na=0,nb=0; if(ditu[mp(va+1,vb)])na=1; if(ditu[mp(va,vb+1)])nb=1; if(na&&!nb)dfs(va,vb+1,4); else if(nb&&!na)dfs(va+1,vb,2); else fanhui=1,dfs(va,vb,3); return ; } else if(d==2){ int w=x+y; int va=(*upper_bound(q2[w].begin(),q2[w].end(),x))-1,vb; vb=w-va; // printf("%d %d ",va,vb); //if(va==4&&vb==2){ // printf("%d %d ",x,y);while(1); //} if(org==d&&sx+sy==w&&sx>=x&&sx<=va){ cishu++; if(cishu!=1){ ans+=abs(sx-x);secs=1;return ; } } ans+=abs(va-x)+1; int na=0,nb=0; if(ditu[mp(va+1,vb)])na=1; if(ditu[mp(va,vb-1)])nb=1; if(na&&!nb)dfs(va,vb-1,3); else if(nb&&!na)dfs(va+1,vb,1); else fanhui=1,dfs(va,vb,4); return ; } else if(d==3){ int w=x-y+m+1; int va=(*--upper_bound(q1[w].begin(),q1[w].end(),x))+1,vb; vb=va-w+m+1; // printf("%d %d ",va,vb); //if(va==4&&vb==2){ // printf("%d %d ",x,y);while(1); //} if(org==d&&sx-sy+m+1==w&&sx<=x&&sx>=va){ cishu++; if(cishu!=1){ ans+=abs(sx-x);secs=1;return ; } } ans+=abs(va-x)+1; int na=0,nb=0; if(ditu[mp(va-1,vb)])na=1; if(ditu[mp(va,vb-1)])nb=1; if(na&&!nb)dfs(va,vb-1,2); else if(nb&&!na)dfs(va-1,vb,4); else fanhui=1,dfs(va,vb,1); return ; } else if(d==4){ int w=x+y; int va=(*--upper_bound(q2[w].begin(),q2[w].end(),x))+1,vb; vb=w-va; // printf("%d %d ",va,vb); //if(va==4&&vb==2){ // printf("%d %d ",x,y);while(1); //} if(org==d&&sx+sy==w&&sx<=x&&sx>=va){ cishu++; if(cishu!=1){ ans+=abs(sx-x);secs=1;return ; } } ans+=abs(va-x)+1; int na=0,nb=0; if(ditu[mp(va-1,vb)])na=1; if(ditu[mp(va,vb+1)])nb=1; if(na&&!nb)dfs(va,vb+1,1); else if(nb&&!na)dfs(va-1,vb,3); else fanhui=1,dfs(va,vb,2); return ; } } int main(){ n=read();m=read();k=read(); for(int i=1,x=0,y=0;i<=k;i++){ x=read();y=read(); q1[x-y+m+1].push_back(x);q2[x+y].push_back(x); ditu[mp(x,y)]=1; } F(j,0,m+1){ q1[-j+m+1].push_back(0); q1[n+1-j+m+1].push_back(n+1); q2[j].push_back(0); q2[n+1+j].push_back(n+1); ditu[mp(0,j)]=1;ditu[mp(n+1,j)]=1; } F(i,0,n+1){ q1[i+m+1].push_back(i); q1[i-m-1+m+1].push_back(i); q2[i].push_back(i); q2[i+m+1].push_back(i); ditu[mp(i,0)]=1;ditu[mp(i,m+1)]=1; } F(i,0,(n+m+2)){ sort(q1[i].begin(),q1[i].end());sort(q2[i].begin(),q2[i].end()); } sx=read();sy=read(); string ch;cin>>ch; if(ch=="SW")org=2; else if(ch=="SE")org=1; else if(ch=="NW")org=3; else if(ch=="NE")org=4; // printf("%d ",org); // pf(ditu[mp(1,10)]); dfs(sx,sy,org); if(fanhui==1)ans>>=1; printf("%lld",ans); } il int read(){ int s=0,f=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();} while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+(ch^48);ch=getchar();} return f?-s:s; } /* g++ 1.cpp -g ./a.out 10 9 10 1 8 6 9 3 6 4 3 10 5 3 4 6 1 10 2 9 8 7 6 10 1 SW */