「2019.7.22 考试」AC和WA0一步之遥
这卷子还是答的挺惨的。
第一题5min写完了,自认为AC(其实WA了80),第二题推了半天CRT的公式老出错结果发现是程序打错了。第三题打模拟150行结果数组没开够,开大就是0->60的转变。状态很差,坏肚子了,一直在去厕所,看来下次早起要吃点素的了。
题解:
T1方程的解。
发现就是个exgcd,先求出gcd和顺带的特解 $ x_0 y_0 $
设 $ gcd(a,b)=d $
这个时候用个通解公式:
$ x=x_0 \frac{c}{d} + k \frac{b}{d} $
$ y=y_0 \frac{c}{d} - k \frac{a}{d} $
那么我们发现方程解的个数就是k的个数。
解个不等式组:
$ x>0 $
$ y>0 $
得到:
$ y_0 \frac{c}{a} < k <-x_0 \frac{c}{b} $
左边向下取整得到l,右边向上去整得到r。
答案个数就是r-l+1,没必要暴力枚举验证啥的,稍low。
加特判就AC,顺提这特判真恶心。
T2 visit
一眼数学题很准,式子推错了没办法。
先说一下错解,大概是分的不太明确,没有把同类分到一组。
设d=T-n-m。
首先d>0并且2|d有解:
我是按照到 $ (n,m) $ 的有效步和无效步算的,这样的话我推出来得式子就是:
$ C_T^{n+m} C_{n+m}^n \sum \limits_{i=0,2|i}^d (C_d^i C_i^{\frac{i}{2}} C_{d-i}^{\frac{d-i}{2}}) $
看一看他什么意思,我把有效的n+m步从T步里分了出来,然后把n步向上的从n+m步中分离开。
剩下的就是d步中的上下左右插空,可以枚举上下走的步数,是i,可以证明他必然是偶数,然后这些步子中必然有 $ \frac{i}{2} $ 步向上,在i步中选出相应的位置,剩下左右走的也可以选出相应的位置。
我们看一下他哪里有问题,问题在于,前面分出来的n步中,是向上走的,他等同于无效步中向上走的步,但是却被我分开计算了。
导致解变多。
正解的话还简单一点,按照方向分布,这样不会出现和我一样的问题。
也就是:
$ \sum \limits_{d=n}^{T-m} C_T^d C_d^{\frac{d-n}{2}} C_{T-d}^{\frac{T-d-m}{2}} $
还是比较简单的,不赘述。
式子出来之后就只剩下板子了,质数小就Lucas算一下,质数多就CRT合并一下,解决了。
T3的话是个大模拟。
一些推论:
1.一个方向上的格子奇偶性不变,所以一个格子最多被从两个相反方向的光射入。
2.黑格子很少,一次循环中反射的次数和n,m,k线性相关。
3.每一条主对角线和副对角线都有一个特殊的编号,可以用x+y和x-y+m来编号。
4.每个格子在一次循环里最多被射两次,只需要记录是否存在反向操作,有的话答案除2。
可以通过坐标二分查找到转角处。
程序写的时候其实可以只写一个判断方向的函数,用这个函数找到他前面的格子,左边的格子和右边的格子,然后用pair存一下,换个函数只需要判断左转右转还是反向,只需要写左转右转反向的函数了,看起来多不过很好水。
那就这么多。
#include<iostream> #include<cstdio> #include<cmath> using namespace std; typedef long long ll; ll T,a,b,c,x,y; ll exgcd(ll a,ll b,ll &x,ll &y) { if(b==0) { x=1;y=0; return a; } ll d=exgcd(b,a%b,x,y); ll tmp=x; x=y; y=tmp-a/b*y; return d; } int main() { scanf("%lld",&T); while(T--) { scanf("%lld%lld%lld",&a,&b,&c); ll d=exgcd(a,b,x,y); ll l=floor(1.0*c/b*(-x)),r=ceil(1.0*c/a*y); ll k=r-l-1; if(a==0&&b==0) { if(c==0) { puts("ZenMeZheMeDuo"); continue; } else { puts("0"); continue; } } if((c%d)) { puts("0"); continue; } if(1LL*a*b<0) { puts("ZenMeZheMeDuo"); continue; } if(a==0) { if(1LL*b*c>0) puts("ZenMeZheMeDuo"); else puts("0"); continue; } if(b==0) { if(1LL*a*c>0) puts("ZenMeZheMeDuo"); else puts("0"); continue; } if(k<0) { puts("0"); continue; } if(k>65535) puts("ZenMeZheMeDuo"); else printf("%lld\n",k); } return 0; }
#include<iostream> #include<cstdio> #include<cmath> using namespace std; typedef long long ll; const int maxn=2e5+5; ll T,mod,n,m,s,fac[maxn],inv[maxn],p[11],ans[11]; ll qw(ll a,ll b,ll ml) { ll ans=1; for(;b;b>>=1,a=a*a%ml) if(b&1) ans=ans*a%ml; return ans; } void moddivide() { ll mm=mod; for(int i=2;1LL*i*i<=mm;i++) if(mm%i==0) { p[++s]=i; mm/=i; } if(mm>1) p[++s]=mm; } ll CRT() { ll b=0; for(int i=1;i<=s;i++) { ll M=mod/p[i]; b+=ans[i]*M%mod*qw(M,p[i]-2,p[i])%mod; b%=mod; } return b; } void Getfac_inv(int p) { fac[0]=inv[0]=1; for(int i=1;i<=min(T,(ll)p);i++) { fac[i]=fac[i-1]*i%p; inv[i]=qw(fac[i],p-2,p); } } ll Get_C(ll n,ll m,ll mod) { if(n<m) return 0; return fac[n]*inv[m]%mod*inv[n-m]%mod; } ll lucas(ll n,ll m,ll p) { if(m==0) return 1; return Get_C(n%p,m%p,p)*lucas(n/p,m/p,p)%p; } int main() { scanf("%lld%lld",&T,&mod); scanf("%lld%lld",&n,&m); n=abs(n);m=abs(m); int d=T-n-m; if(d<0||(d&1)) { puts("0"); return 0; } moddivide(); ll aa; for(int j=1;j<=s;j++) { Getfac_inv(p[j]); aa=0; for(int i=n;i<=T-m;i+=2) { ll tmp=lucas(T,i,p[j])*lucas(i,(i-n)/2,p[j])%p[j]*lucas(T-i,(T-i-m)/2,p[j])%p[j]; aa+=tmp; aa%=p[j]; } ans[j]=aa; } printf("%lld\n",CRT()); return 0; }
#include<iostream> #include<cstdio> #include<cmath> #include<vector> #include<algorithm> #include<map> #define mr(a,b) make_pair(a,b) using namespace std; typedef long long ll; const int ne=1,se=2,sw=3,nw=4,maxn=1e5+5,tmp=maxn+10; const int xi[5]={0,-1,+1,+1,-1},yi[5]={0,+1,+1,-1,-1}; vector<int> man[maxn<<1],rst[maxn<<1]; map<ll,int> mp; map<pair<int,pair<int,int> >,int> up; int n,m,k,x,y,sx,sy,nx,ny,fr,dr,flag; ll ans; char s[5]; int jud() { if(s[1]=='N'&&s[2]=='E') return sw; if(s[1]=='N'&&s[2]=='W') return se; if(s[1]=='S'&&s[2]=='E') return nw; if(s[1]=='S'&&s[2]=='W') return ne; } int right(int x) { if(x==ne) return se; if(x==se) return sw; if(x==sw) return nw; if(x==nw) return ne; } int left(int x) { if(x==ne) return nw; if(x==nw) return sw; if(x==sw) return se; if(x==se) return ne; } int ni(int x) { if(x==ne) return sw; if(x==se) return nw; if(x==sw) return ne; if(x==nw) return se; } int lt(int &x,int &y,int dir) { if(dir==se) y++; if(dir==ne) x--; if(dir==sw) x++; if(dir==nw) y--; } int rt(int &x,int &y,int dir) { if(dir==se) x++; if(dir==ne) y++; if(dir==sw) y--; if(dir==nw) x--; } int change(pair<int,pair<int,int> > d,int dir,int &x,int &y) { int a=d.first,b=d.second.first,c=d.second.second; if(a) { if(b&&c) { flag=1; return ni(dir); } if((!b)&&c) { lt(x,y,dir); return left(dir); } if(b&&(!c)) { rt(x,y,dir); return right(dir); } if((!b)&&(!c)) { flag=1; return ni(dir); } } else { x+=xi[dir];y+=yi[dir]; return dir; } } pair<int,pair<int,int> > gnum(int x,int y,int dir) { pair<int,pair<int,int> > a; if(dir==sw) { a.first=mp[1LL*(x+1)*tmp+y-1]; a.second.first=mp[1LL*(x+1)*tmp+y]; a.second.second=mp[1LL*x*tmp+y-1]; } if(dir==nw) { a.first=mp[1LL*(x-1)*tmp+y-1]; a.second.first=mp[1LL*tmp*x+y-1]; a.second.second=mp[1LL*tmp*(x-1)+y]; } if(dir==ne) { a.first=mp[1LL*(x-1)*tmp+y+1]; a.second.first=mp[1LL*(x-1)*tmp+y]; a.second.second=mp[1LL*x*tmp+y+1]; } if(dir==se) { a.first=mp[1LL*(x+1)*tmp+y+1]; a.second.first=mp[1LL*x*tmp+y+1]; a.second.second=mp[1LL*(x+1)*tmp+y]; } return a; } pair<int,int> find(int x,int y,int r) { if(r==ne) { int t=lower_bound(rst[x+y].begin(),rst[x+y].end(),x)-rst[x+y].begin()-1; t=rst[x+y][t]+1; return mr(t,x+y-t); } if(r==se) { int t=lower_bound(man[x-y+m+1].begin(),man[x-y+m+1].end(),x)-man[x-y+m+1].begin(); t=man[x-y+m+1][t]-1; return mr(t,-(x-y-t)); } if(r==sw) { int t=lower_bound(rst[x+y].begin(),rst[x+y].end(),x)-rst[x+y].begin(); t=rst[x+y][t]-1; return mr(t,x+y-t); } if(r==nw) { int t=lower_bound(man[x-y+m+1].begin(),man[x-y+m+1].end(),x)-man[x-y+m+1].begin()-1; t=man[x-y+m+1][t]+1; return mr(t,-(x-y-t)); } } void work(int x,int y,int dr) { for(int i=1;i<=4;i++) if(dr==i) { pair<int,int> nxt=find(x,y,i); ans+=abs(nxt.first-nx)+1; nx=nxt.first;ny=nxt.second; return ; } } int main() { scanf("%d%d%d",&n,&m,&k); while(k--) { scanf("%d%d",&x,&y); man[x-y+m+1].push_back(x); rst[x+y].push_back(x); mp[1LL*x*tmp+y]=1; } for(int i=1;i<=m;i++) { mp[0*tmp+i]=1;mp[1LL*tmp*(n+1)+i]=1; man[0-i+m+1].push_back(0); rst[0+i].push_back(0); man[n+1-i+m+1].push_back(n+1); rst[n+i+1].push_back(n+1); } for(int i=1;i<=n;i++) { mp[1LL*i*tmp+0]=1;mp[1LL*i*tmp+m+1]=1; man[i-0+m+1].push_back(i); rst[i+0].push_back(i); man[i-m-1+m+1].push_back(i); rst[i+m+1].push_back(i); } mp[0]=1;mp[1LL*tmp*(n+1)+0]=1;mp[1LL*0*tmp+m+1]=1;mp[1LL*tmp*(n+1)+m+1]=1; man[0-0+m+1].push_back(0); rst[0+0].push_back(0); man[n+1-0+m+1].push_back(n+1); rst[n+1+0].push_back(n+1); man[0-m-1+m+1].push_back(0); rst[0+m+1].push_back(0); man[n+1-m-1+m+1].push_back(n+1); rst[n+1+m+1].push_back(n+1); for(int i=0;i<=max(n,m)*2+2;i++) sort(man[i].begin(),man[i].end()); for(int i=0;i<=max(n,m)*2+2;i++) sort(rst[i].begin(),rst[i].end()); scanf("%d%d",&sx,&sy); scanf("%s",s+1); nx=sx;ny=sy;fr=dr=jud(); work(nx,ny,dr); pair<int,pair<int,int> > dd=gnum(nx,ny,dr); dr=change(dd,dr,nx,ny); sx=nx;sy=ny;fr=dr; ans=0; do { work(nx,ny,dr); pair<int,pair<int,int> > dd=gnum(nx,ny,dr); dr=change(dd,dr,nx,ny); }while(!(nx==sx&&ny==sy&&dr==fr)); printf("%lld\n",ans>>flag); return 0; }