20190722
今天的题还是很水的,但还是挽救不了我
T1.方程的解
除了一堆特判别的好像啥都没有。
还好前一天自己仔细研究了一下扩欧的板子,起码板子打对了。
记一下错因吧。
方程通解为x=cx0/d+kb/d y=cy0/d-ka/d
我通过求k的范围确定了解的个数,但实际上应该用ymax-ymin求解个数
1 #include <cstdio> 2 #define re register 3 #define int long long 4 using namespace std; 5 int hp_and_rp; 6 inline int exgcd(re int a,re int b,re int c,re int &x,re int &y){ 7 if(b==0){ 8 y=0; 9 x=c/a; 10 return a; 11 } 12 re int g=exgcd(b,a%b,c,y,x); 13 y-=(a/b)*x; 14 return g; 15 } 16 main(){ 17 scanf("%lld",&hp_and_rp); 18 while(hp_and_rp--) 19 { 20 re int a,b,c,x,y; 21 re bool flag_a=0,flag_b=0; 22 scanf("%lld%lld%lld",&a,&b,&c); 23 if(c<0)a=-a,b=-b,c=-c; 24 if(a<0)a=-a,flag_a=1; 25 if(b<0)b=-b,flag_b=1; 26 re int g=exgcd(a,b,c,x,y); 27 if(c%g){puts("0");continue;} 28 if(a*x+b*y!=c){puts("0");continue;} 29 if(flag_a)a=-a,x=-x; 30 if(flag_b)b=-b,y=-y; 31 if(a==0){ 32 if(y<=0){ 33 puts("0"); 34 }else{ 35 puts("ZenMeZheMeDuo"); 36 } 37 continue; 38 } 39 if(b==0){ 40 if(x<=0){ 41 puts("0"); 42 }else{ 43 puts("ZenMeZheMeDuo"); 44 } 45 continue; 46 } 47 if(a*b<0){ 48 puts("ZenMeZheMeDuo"); 49 continue; 50 } 51 if(a<0)a=-a,b=-b,c=-c; 52 a/=g,b/=g,c/=g,x%=b; 53 while(x<=0)x+=b; 54 y=(c-a*x)/b; 55 re int ymin=y%a; 56 while(ymin<=0)ymin+=a; 57 re int ans; 58 if(ymin>y)ans=0; 59 else ans=(y-ymin)/a+1; 60 if(ans>65535)puts("ZenMeZheMeDuo"); 61 else printf("%lld\n",ans); 62 } 63 }
T2.visit
我才不会说出来我开心地把 树上染色 码完了
这个题....我打了个矩阵快速幂,空间n4 时间n6
呵呵。。。。我%^&^&$*
我也没想拿太多分,只想要个20的部分分,然鹅....呵呵
1 #include <map> 2 #include <ctime> 3 #include <cmath> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <cstring> 7 #include <iostream> 8 #include <algorithm> 9 using namespace std; 10 #define QAQ 444 11 #define re register 12 #define ll long long 13 #define pt pair<int,int> 14 #define mp(a,b) make_pair(a,b) 15 #define fup(i,a,b) for(re int i=a;i<=b;++i) 16 #define fdn(i,a,b) for(re int i=a;i>=b;--i) 17 inline int random(re int n){ 18 return (ll)rand()*rand()%n; 19 } 20 int t,mod,n,tot,m; 21 map< pt,int >mmp; 22 inline int read(){ 23 re int x(0),f(1);re char ch=getchar(); 24 while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} 25 while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} 26 return x*f; 27 } 28 struct huaQ{ 29 int mat[666][666]; 30 inline void clear(){ 31 memset(mat,0,sizeof mat); 32 } 33 inline void print(){ 34 fup(i,1,n){ 35 fup(j,1,n) 36 printf("%d",mat[i][j]); 37 puts(""); 38 } 39 puts("******************"); 40 } 41 }niknikni; 42 huaQ operator * (const huaQ &a,const huaQ &b){ 43 huaQ c;c.clear(); 44 fup(i,1,n)fup(j,1,n)fup(k,1,n) 45 { 46 c.mat[i][j]+=a.mat[i][k]*b.mat[k][j]; 47 c.mat[i][j]%=mod; 48 } 49 return c; 50 } 51 inline huaQ quick_fk_me(re huaQ a,re int b){ 52 huaQ ans=a;--b; 53 for(;b;b>>=1){ 54 if(b&1)ans=ans*a; 55 a=a*a; 56 } 57 return ans; 58 } 59 int main(){ 60 srand((unsigned)time(0)); 61 re int x,y; 62 huaQ niknikni; 63 niknikni.clear(); 64 t=read(),mod=read(); 65 x=read(),y=read(); 66 if(t*t>=666){ 67 printf("%d",random(mod)); 68 return 0; 69 } 70 fup(i,-t,t){ 71 fup(j,-t,t){ 72 //printf("%d %d ",i,j); 73 pt kkk=mp(i,j); 74 mmp[kkk]=++tot; 75 //printf("%d\n",tot); 76 } 77 } 78 n=tot; 79 fup(i,1,tot){ 80 if(i%(2*t+1)) 81 niknikni.mat[i][i+1]=1; 82 if(i%(2*t+1)!=1) 83 niknikni.mat[i][i-1]=1; 84 if(i-(2*t+1)>=1) 85 niknikni.mat[i][i-2*t-1]=1; 86 if(i+(2*t+1)<=tot) 87 niknikni.mat[i][i+2*t+1]=1; 88 } 89 //niknikni.print(); 90 huaQ ans=quick_fk_me(niknikni,t); 91 //pt fff=mp(2,1); 92 //printf("%d",mmp[fff]); 93 pt st=mp(0,0),ed=mp(x,y); 94 //printf("%d %d\n",mmp[st],mmp[ed]); 95 //ans.print(); 96 if(ans.mat[mmp[st]][mmp[ed]]<=0)printf("%d",random(mod)); 97 else printf("%d",ans.mat[mmp[st]][mmp[ed]]); 98 }
正解是组合数。
这是一道很好的数论拼盘。Lucas CRT 逆元 分解质因数....
改题时选择了数据点分治一直过不去....
发现不分治直接wa0 我???
后来发现有一个分支没求阶乘妈耶。
式子很好推
我选择了lyl的式子
C(t,k)*C(t-k,k-m)*C(t-2k+m,(t-2k+m+n)/2)
式子好理解
设k为向上走的步数(纯的,不包括向下),那么向下走的步数为k-m
即C(T,k)×C(T-k,k-m);
由上式可推出 向右的与向左的步数之和为T-2*k+m,而向右的比向左的多n,利用和差公式,易得,向右的为(T-2*k+m+n)/2;
且k>=m,(T-2*k+m+n)/2>=n;可得,k->[m,(T+m-n)/2];
故整体公式为
∑(k->[m,(T+m-n)/2])(C(T,k)×C(T-k,k-m)×C(T-2*k+m,(T-2*k+m+n)/2));
(引用lyl)
枚举k 注意范围 k-m>=0 (t-2k+m+n)/2>=n
主要还是实现卡了一下午
对CRT理解不够
这个题的ans % mod的解
可以看为一个线性同余方程组
ans%p1=ans1
ans%p2=ans2
......
ans%pi=ansi
pi为分解后的质因数,ansi对于pi取模后的解,用CRT可以合并
有个ZZ的细节是阶乘、逆元要预处理
对于每一个pi处理一组阶乘和逆元
1 #include <cmath> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 using namespace std; 6 #define QAQ 100010 7 #define re register 8 #define int long long 9 #define ll long long 10 #define fup(i,a,b) for(re int i=a;i<=b;++i) 11 #define fdn(i,a,b) for(re int i=a;i>=b;--i) 12 int n,m,mod,t; 13 ll ans; 14 int fac[QAQ],inv[QAQ]; 15 void exgcd(re ll a,re ll b,re ll &x,re ll &y){ 16 if(b==0){x=1,y=0;return;} 17 exgcd(b,a%b,x,y); 18 re int z=x; 19 x=y,y=z-a/b*y; 20 } 21 inline ll crt(){ 22 re ll ans=0,lcm=1,x,y; 23 fup(i,1,tot)lcm*=p[i]; 24 fup(i,1,tot){ 25 re ll tmp=lcm/p[i]; 26 exgcd(tmp,p[i],x,y); 27 x=(x%p[i]+p[i])%p[i]; 28 ans=(ans+tmp*x*w[i])%lcm; 29 } 30 return (ans+lcm)%lcm; 31 } 32 inline void Get_fac_and_inv(re int top,re int pk){ 33 fac[0]=fac[1]=inv[0]=inv[1]=1; 34 fup(i,2,top)fac[i]=1ll*fac[i-1]*i%pk; 35 fup(i,2,top)inv[i]=(pk-pk/i)*inv[pk%i]%pk; 36 fup(i,1,top)inv[i]=1ll*inv[i-1]*inv[i]%pk; 37 } 38 int CC(re int n,re int m,re int pk){ 39 if(m>n)return 0; 40 return fac[n]*inv[m]%pk*inv[n-m]%pk; 41 } 42 int lucas(re int n,re int m,re int pk){ 43 if(!m)return 1; 44 return CC(n%pk,m%pk,pk)*lucas(n/pk,m/pk,pk)%pk; 45 } 46 inline bool divide(int n){ 47 re int top=sqrt(n); 48 fup(i,2,top){ 49 if(n%i)continue; 50 p[++tot]=i; 51 while(n%i==0)n/=i; 52 } 53 if(n>1)p[++tot]=n; 54 return tot==1; 55 } 56 main(){ 57 scanf("%lld%lld",&t,&mod); 58 scanf("%lld%lld",&n,&m); 59 if(n<0)n=-n; 60 if(m<0)m=-m; 61 re int st=m,ed=(t+m-n)>>1; 62 if(divide(mod)){ 63 Get_fac_and_inv(min(t,mod),mod);//什么纱吊错 妈耶 不求阶乘??!! 64 fup(k,st,ed) 65 ans=(ans+lucas(t,k,mod)*lucas(t-k,k-m,mod)%mod*lucas(t-2*k+m,(t-2*k+m-n)>>1,mod)%mod)%mod; 66 printf("%lld\n",ans); 67 return 0; 68 } 69 fup(i,1,tot){ 70 re int pk=p[i]; 71 Get_fac_and_inv(min(t,pk),pk); 72 fup(k,st,ed) 73 w[i]=(w[i]+lucas(t,k,pk)*lucas(t-k,k-m,pk)%pk*lucas(t-2*k+m,(t-2*k+m-n)>>1,pk)%pk)%pk; 74 } 75 printf("%lld\n",crt()); 76 }
T3.光(大模拟)
1,每一个格子只会被 左下<->右上 \ 左上<->右下 两种光线的其中一种经过。
2,光线的路径一定是一个完整的环,而不是环+链。也就是说,它一定还会不止一次的以起始状态经过起始点。
证明详见DeepinC
有了这个结论就可以做了
首先 对于左上、右下,x-y的值不变 即每一个x-y都对应着唯一的一条直线
同理 左下、右上 x+y的值不变 也对应着一条直线
所以我们就可以求出每一条直线上的障碍情况 通过二分找到当前位置的前驱或后继 即确定下一步撞到哪
据题意就可以模拟光的反射了
当我用map<pair<int,int>,bool>存下所有的障碍坐标时,有人说可以优化暴力,其实时间复杂度是撑不住的
在正解中你只会撞障碍 过程是不考虑的
因而有一个小细节 什么时候停止?
当且仅当回到起点且方向相同时。
但是不是只撞障碍吗?
所以你可以单步模拟一次让它相当与从一个障碍处出发 当然这个过程不计入答案
1 #include <set>
2 #include <map>
3 #include <cmath>
4 #include <cstdio>
5 #include <vector>
6 #include <iostream>
7 using namespace std;
8 #define QAQ 100000
9 #define re register
10 #define ll long long
11 #define pt pair<int,int>
12 #define mp(a,b) make_pair(a,b)
13 #define fup(i,a,b) for(re int i=a;i<=b;++i)
14 int n,m,k,stx,sty,now;
15 ll ans;
16 set<int>wtf1[QAQ<<1],wtf2[QAQ<<1];
17 map<pt,bool>mmp;
18 inline int read(){
19 re int x(0),f(1);re char ch=getchar();
20 while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
21 while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
22 return x*f;
23 }
24 inline int order(char *ch){
25 if(ch[0]=='N'&&ch[1]=='E')return 1;
26 if(ch[0]=='N'&&ch[1]=='W')return 2;
27 if(ch[0]=='S'&&ch[1]=='E')return 3;
28 if(ch[0]=='S'&&ch[1]=='W')return 4;
29 }
30 int main(){
31 re char op[3];
32 n=read(),m=read(),k=read();
33 fup(i,1,k){
34 re int x,y;
35 x=read(),y=read();
36 mmp[mp(x,y)]=1;
37 wtf1[x+y].insert(x);
38 wtf2[x-y+QAQ].insert(x);
39 }
40 fup(i,0,n+1){
41 mmp[mp(i,0)]=1;
42 mmp[mp(i,m+1)]=1;
43 wtf1[i+0].insert(i);
44 wtf2[i-0+QAQ].insert(i);
45 wtf1[i+m+1].insert(i);
46 wtf2[i-m-1+QAQ].insert(i);
47 }
48 fup(i,1,m){
49 mmp[mp(0,i)]=1;
50 mmp[mp(n+1,i)]=1;
51 wtf1[0+i].insert(0);
52 wtf2[0-i+QAQ].insert(0);
53 wtf1[n+1+i].insert(n+1);
54 wtf2[n+1-i+QAQ].insert(n+1);
55 }
56 stx=read(),sty=read();scanf("%s",op);
57 now=order(op);
58 re int x=stx,y=sty,tox,toy,st,flag=0,ok=0;
59 switch(now){
60 case 1 : {
61 tox=*--wtf1[x+y].lower_bound(x);
62 toy=x+y-tox;
63 pt judge=mp(tox+1,toy);
64 pt judge2=mp(tox,toy-1);
65 bool fu=mmp[judge],ck=mmp[judge2];
66 if(fu&&ck)now=4,flag=1;
67 else if(fu)now=2,++tox;
68 else if(ck)now=3,--toy;
69 else now=4,flag=1;
70 x=tox,y=toy;
71 break;}
72 case 2 : {
73 tox=*--wtf2[x-y+QAQ].lower_bound(x);
74 toy=tox-x+y;
75 pt judge=mp(tox+1,toy);
76 pt judge2=mp(tox,toy+1);
77 bool fu=mmp[judge],ck=mmp[judge2];
78 if(fu&&ck)now=3,flag=1;
79 else if(fu)now=1,++tox;
80 else if(ck)now=4,++toy;
81 else now=3,flag=1;
82 x=tox,y=toy;
83 break;}
84 case 3 : {
85 tox=*wtf2[x-y+QAQ].upper_bound(x);
86 toy=tox-x+y;
87 pt judge=mp(tox-1,toy);
88 pt judge2=mp(tox,toy-1);
89 bool fu=mmp[judge],ck=mmp[judge2];
90 if(fu&&ck){now=2;}
91 if(mmp[judge]){now=4,--tox;}
92 else if(ck){now=1,--toy;}
93 else now=2;
94 x=tox,y=toy;
95 break;}
96 case 4 : {
97 tox=*wtf1[x+y].upper_bound(x);
98 toy=x+y-tox;
99 pt judge=mp(tox-1,toy);
100 pt judge2=mp(tox,toy+1);
101 bool fu=mmp[judge],ck=mmp[judge2];
102 if(fu&&ck){now=1;}
103 else if(fu){now=3,--tox;}
104 else if(ck){now=2,++toy;}
105 else now=1;
106 x=tox,y=toy;
107 break;}
108 }
109 stx=x,sty=y,st=now;
110 while(1){
111 if(ok)break;
112 switch(now){
113 case 1 : {
114 if(x==stx&&y==sty&&ans!=0&&now==st){ok=1;break;}
115 tox=*--wtf1[x+y].lower_bound(x);
116 toy=x+y-tox;
117 ans+=abs(toy-y)-1;
118 pt judge=mp(tox+1,toy);
119 pt judge2=mp(tox,toy-1);
120 bool fu=mmp[judge],ck=mmp[judge2];
121 if(fu&&ck)now=4,flag=1;
122 else if(fu)now=2,++tox;
123 else if(ck)now=3,--toy;
124 else now=4,flag=1;
125 x=tox,y=toy;
126 break;}
127 case 2 : {
128 if(x==stx&&y==sty&&ans!=0&&now==st){ok=1;break;}
129 tox=*--wtf2[x-y+QAQ].lower_bound(x);
130 toy=tox-x+y;
131 ans+=abs(toy-y)-1;
132 pt judge=mp(tox+1,toy);
133 pt judge2=mp(tox,toy+1);
134 bool fu=mmp[judge],ck=mmp[judge2];
135 if(fu&&ck)now=3,flag=1;
136 else if(fu)now=1,++tox;
137 else if(ck)now=4,++toy;
138 else now=3,flag=1;
139 x=tox,y=toy;
140 break;}
141 case 3 : {
142 if(x==stx&&y==sty&&ans!=0&&now==st){ok=1;break;}
143 tox=*wtf2[x-y+QAQ].upper_bound(x);
144 toy=tox-x+y;
145 ans+=abs(toy-y)-1;
146 pt judge=mp(tox-1,toy);
147 pt judge2=mp(tox,toy-1);
148 bool fu=mmp[judge],ck=mmp[judge2];
149 if(fu&&ck)now=2,flag=1;
150 else if(fu)now=4,--tox;
151 else if(ck)now=1,--toy;
152 else now=2,flag=1;
153 x=tox,y=toy;
154 break;}
155 case 4 : {
156 if(x==stx&&y==sty&&ans!=0&&now==st){ok=1;break;}
157 tox=*wtf1[x+y].upper_bound(x);
158 toy=x+y-tox;
159 ans+=abs(toy-y)-1;
160 pt judge=mp(tox-1,toy);
161 pt judge2=mp(tox,toy+1);
162 bool fu=mmp[judge],ck=mmp[judge2];
163 if(fu&&ck)now=1,flag=1;
164 else if(fu)now=3,--tox;
165 else if(ck)now=2,++toy;
166 else now=1,flag=1;
167 x=tox,y=toy;
168 break;}
169 }
170 }
171 if(flag)ans>>=1;
172 printf("%lld",ans);
173 }