NOIp2018集训test-10-20 (bike day6)
B 君的第一题 lanzhou
$x^{\frac{p-1}{2}}\equiv 1(mod\ p)$
$x\equiv x*x^{\frac{p-1}{2}} (mod\ p)$
$x\equiv x^{\frac{p+1}{2}} (mod\ p)$
$\sqrt{x}\equiv x^{\frac{p+1}{4}} (mod\ p)$
就成了一道快速幂的题了,然而唯二A了的我和李巨都是用类似复数快速幂那种方法暴力开根号。
我:这道题感觉没意义啊,会二次剩余的暴力开根也开出来了,不会的怎么都GG了。
李巨:没有啊,你只要会费马小定理这个题随便推吧。
(数学一窍不通—根本推不出来的)我:%%%
要是7个月前我会开根号的话现在我大概就不在这里了吧。
1 //Achen
2 #include<bits/stdc++.h>
3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
5 #define Formylove return 0
6 const int p=1000000007,inv2=500000004,inv4=250000002;
7 typedef long long LL;
8 typedef double db;
9 using namespace std;
10 int T;
11 LL b,c;
12
13 template<typename T> void read(T &x) {
14 char ch=getchar(); x=0; T f=1;
15 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
16 if(ch=='-') f=-1,ch=getchar();
17 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
18 }
19
20 LL w;
21 struct fs {
22 LL a,b;
23 fs(){}
24 fs(LL a,LL b):a(a),b(b){}
25 };
26
27 LL mo(LL x) { return x<0?x+p:(x>=p?x-p:x); }
28
29 fs operator +(const fs&A,const fs&B) { return fs(mo(A.a+B.a),mo(A.b+B.b)); }
30 fs operator *(const fs&A,const fs&B) { return fs(mo(A.a*B.a%p+A.b*B.b%p*w%p),mo(A.a*B.b%p+A.b*B.a%p)); }
31
32 LL fsksm(fs a,LL b) {
33 fs rs=fs(1,0),bs=a;
34 while(b) {
35 if(b&1) rs=rs*bs;
36 bs=bs*bs;
37 b>>=1;
38 }
39 return rs.a;
40 }
41
42 LL ksm(LL a,LL b) {
43 LL bs=a%p,rs=1;
44 while(b) {
45 if(b&1) rs=rs*bs%p;
46 bs=bs*bs%p;
47 b>>=1;
48 }
49 return rs;
50 }
51
52 int ck(LL x) { return ksm(x,(p-1)/2)==1; }
53
54 LL get_sqr(LL x) {
55 LL a=rand()%p+1;
56 while(ck(mo(a*a%p-x))) {
57 a=rand()%p+1;
58 }
59 w=mo(a*a%p-x);
60 return fsksm(fs(a,1),(p+1)/2);
61 }
62
63 #define ANS
64 int main() {
65 #ifdef ANS
66 freopen("lanzhou.in","r",stdin);
67 freopen("lanzhou.out","w",stdout);
68 #endif
69 srand(998244353);
70 read(T);
71 For(cs,1,T) {
72 read(b); read(c);
73 LL x=(b*b%p*inv4%p-c+p)%p;
74 if(!x) {
75 LL m1=b*inv2%p;
76 LL m2=mo(b-m1);
77 if(m1>m2) swap(m1,m2);
78 printf("%lld %lld\n",m1,m2);
79 }
80 else if(ck(x)) {
81 LL y=get_sqr(x);
82 LL m1=mo(y+b*inv2%p);
83 LL m2=mo(b-m1);
84 if(m1>m2) swap(m1,m2);
85 printf("%lld %lld\n",m1,m2);
86 }
87 else puts("-1 -1");
88 }
89 Formylove;
90 }
B 君的第二题 xining
Bike老爷专门卡kmp,成功卡掉了一个机房。
因为有退格操作,可能aaaaaaaab-b-b-b-b这样的数据就会一直跳,所以要把自动机建出来,也就是保存下每个位置选择a~z每个字母时会走到哪里。
同理AC自动机也是,sxy和llj的写法都是要补全儿子的,我以前那种不补全儿子的写法就可以被某些题卡。
1 //Achen
2 #include<bits/stdc++.h>
3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
5 #define Formylove return 0
6 const int N=300007;
7 typedef long long LL;
8 typedef double db;
9 using namespace std;
10 char s[N],op[N];
11 int nxt[N],n,ts[N][26];
12
13 template<typename T> void read(T &x) {
14 char ch=getchar(); x=0; T f=1;
15 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
16 if(ch=='-') f=-1,ch=getchar();
17 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
18 }
19
20 #define ANS
21 int main() {
22 #ifdef ANS
23 freopen("xining.in","r",stdin);
24 freopen("xining.out","w",stdout);
25 #endif
26 memset(ts,-1,sizeof(ts));
27 scanf("%s",s);
28 scanf("%s",op);
29 int lena=strlen(s);
30 s[lena]='&';
31 memset(ts[0],0,sizeof(ts[0]));
32 for(int i=1,k=0;i<=lena;i++) {
33 For(x,0,25) {
34 if(x==s[k]-'a') ts[i][x]=k+1;
35 else if(!k) ts[i][x]=k;
36 else {
37 if(x==s[nxt[k-1]]-'a') ts[i][x]=nxt[k-1]+1;
38 else ts[i][x]=ts[nxt[k-1]][x];
39 }
40 }
41 k=ts[i][s[i]-'a'];
42 nxt[i]=k;
43 }
44 int leno=strlen(op);
45 int i=lena,k=0;
46 printf("%d\n",lena);
47 For(cs,0,leno-1) {
48 if(op[cs]=='-') {
49 if(i>lena) {
50 nxt[i]=0;
51 memset(ts[i+1],-1,sizeof(ts[i+1]));
52 i--;
53 k=nxt[i];
54 }
55 }
56 else {
57 s[++i]=op[cs];
58 For(x,0,25) {
59 if(x==s[k]-'a') ts[i][x]=k+1;
60 else if(!k) ts[i][x]=k;
61 else {
62 if(x==s[nxt[k-1]]-'a') ts[i][x]=nxt[k-1]+1;
63 else ts[i][x]=ts[nxt[k-1]][x];
64 }
65 }
66 k=ts[i][op[cs]-'a'];
67 nxt[i]=k;
68 }
69 printf("%d\n",lena-nxt[i]);
70 }
71 Formylove;
72 }
73 /*
74 aaa
75 aaaaaaab-b-b-b-b-
76 */
B 君的第三题 yinchuan
ORZ哥德巴赫猜想,我对数学一窍不通还真是对不起了。(从小从没学过数竟,初中在贫困山区的破烂学校上的,再有名我都不知道)
首先区间操作想到差分,每个点表示它和它前面一个点是否相同。现在翻转一个区间变成了翻转两个点,最终使序列全为0。
一次翻转i,j两个点的代价:
|i-j|为奇质数:1
|i-j|为偶数(根据哥德巴赫猜想,大于等于6的偶数都能拆成两个奇质数之和,2=5-3,4=7-3):2
|i-j|为奇合数:3(先变成偶数再2次操作)
那么容易发现翻转0一定不优,每次都是翻转两个1,且1的个数一定为偶数。
那么把1的位置按奇偶分类,差的绝对值为奇质数的连边,二分图匹配。剩下的左边跟左边配右边跟右边配,最多左右各剩一个就左右配。
1 //Achen
2 #include<bits/stdc++.h>
3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
5 #define Formylove return 0
6 const int N=107,up=10009;
7 typedef long long LL;
8 typedef double db;
9 using namespace std;
10 int n,a[N],b[N],c[N],ans;
11
12 template<typename T> void read(T &x) {
13 char ch=getchar(); x=0; T f=1;
14 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
15 if(ch=='-') f=-1,ch=getchar();
16 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
17 }
18
19 int bo[up+7],p[up+7];
20 void get_prime() {
21 For(i,2,up) {
22 if(!bo[i]) p[++p[0]]=i;
23 for(int j=1;j<=p[0]&&i*p[j]<=up;j++) {
24 bo[i*p[j]]=1;
25 if(i%p[j]==0) break;
26 }
27 }
28 bo[1]=bo[2]=1;
29 }
30
31 void GM(LL &x,LL y) { if(x>y) x=y; }
32
33 int vis[N],pr[N],mp[N][N];
34 int find(int x) {
35 For(i,1,c[0]) if(mp[x][i]&&!vis[i]) {
36 vis[i]=1;
37 if(!pr[i]||find(pr[i])) {
38 pr[i]=x;
39 return 1;
40 }
41 }
42 return 0;
43 }
44
45 #define ANS
46 int main() {
47 #ifdef ANS
48 freopen("yinchuan.in","r",stdin);
49 freopen("yinchuan.out","w",stdout);
50 #endif
51 read(n);
52 get_prime();
53 For(i,1,n) read(a[i]);
54 For(i,1,n) {
55 if(i==1||a[i-1]!=a[i]-1) {
56 if(a[i]&1) b[++b[0]]=a[i];
57 else c[++c[0]]=a[i];
58 }
59 if(a[i+1]!=a[i]+1) {
60 if((a[i]+1)&1) b[++b[0]]=a[i]+1;
61 else c[++c[0]]=a[i]+1;
62 }
63 }
64 For(i,1,b[0]) For(j,1,c[0]) {
65 if(!bo[abs(b[i]-c[j])]) mp[i][j]=1;
66 }
67 For(i,1,b[0]) {
68 memset(vis,0,sizeof(vis));
69 ans+=find(i);
70 }
71 if((b[0]-ans)&1) ans=ans+(b[0]-ans)/2*2+(c[0]-ans)/2*2+3;
72 else ans=ans+(b[0]-ans)+(c[0]-ans);
73 printf("%d\n",ans);
74 Formylove;
75 }