Beta Round #9 (酱油杯noi考后欢乐赛)PLQ和他的小伙伴们

题目:http://www.contesthunter.org/contest/Beta%20Round%20%EF%BC%839%20%28%E9%85%B1%E6%B2%B9%E6%9D%AFnoi%E8%80%83%E5%90%8E%E6%AC%A2%E4%B9%90%E8%B5%9B%29/PLQ%E5%92%8C%E4%BB%96%E7%9A%84%E5%B0%8F%E4%BC%99%E4%BC%B4%E4%BB%AC

题解:先给题目点个赞!真是一道好题!

刚开始看见真是一点思路都没有,后来看见简要题解说KMP,不知道怎么用。。。

今天忽然有了思路,我们假设从1开始,然后可以得到一个惊呆序列,并且把每个人的惊呆指数记下来,得到一个数列a[i]。

那么这个数列是由从谁开始数1唯一确定的,比如从i开始i最后的惊讶指数就是a[1],i+1就是a[2],也就是我们保持了一个相对的位置关系。

那我们对由a对b做字符串匹配,(先把a在后面复制一遍),假设匹配成功点是i,那么i-n+1就是1是从起始点开始数的第几个人,我们就可以得出起始点是谁。

一道漂亮的题!

推起始点那里蛋疼了好久。。。

代码:

 1 #include<cstdio>
 2 
 3 #include<cstdlib>
 4 
 5 #include<cmath>
 6 
 7 #include<cstring>
 8 
 9 #include<algorithm>
10 
11 #include<iostream>
12 
13 #include<vector>
14 
15 #include<map>
16 
17 #include<set>
18 
19 #include<queue>
20 
21 #include<string>
22 
23 #define inf 1000000000
24 
25 #define maxn 2000000+5
26 
27 #define maxm 500+100
28 
29 #define eps 1e-10
30 
31 #define ll long long
32 
33 #define pa pair<int,int>
34 
35 #define for0(i,n) for(int i=0;i<=(n);i++)
36 
37 #define for1(i,n) for(int i=1;i<=(n);i++)
38 
39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
40 
41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
42 
43 #define mod 1000000007
44 
45 using namespace std;
46 
47 inline int read()
48 
49 {
50 
51     int x=0,f=1;char ch=getchar();
52 
53     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
54 
55     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
56 
57     return x*f;
58 
59 }
60 int n,m,a[maxn],b[maxn],next[maxn],ans[maxn],tot;
61 
62 int main()
63 
64 {
65 
66     freopen("input.txt","r",stdin);
67 
68     freopen("output.txt","w",stdout);
69 
70     n=read();m=read();int x=-1;
71     for1(i,m)a[((x+=read())%=n)+1]++;
72     for1(i,n)a[n+i]=a[i];
73     for1(i,n)b[i]=read();
74     int j=0;
75     for2(i,2,n)
76     {
77         while(j&&b[j+1]!=b[i])j=next[j];
78         if(b[j+1]==b[i])j++;
79         next[i]=j;
80     }
81     j=0;
82     for1(i,2*n-1)
83     {
84         while(j&&b[j+1]!=a[i])j=next[j];
85         if(b[j+1]==a[i])j++;
86         if(j==n)ans[++tot]=(2*n+1-i)%n?(2*n+1-i)%n:n,j=next[j];
87     }
88     if(tot!=1){printf("Cannot determine!\n");printf("%d\n",tot);}else printf("%d\n",ans[1]);
89 
90     return 0;
91 
92 } 
View Code

 改了其中的一些细节,好像更容易理解?

代码:

 1 #include<cstdio>
 2 
 3 #include<cstdlib>
 4 
 5 #include<cmath>
 6 
 7 #include<cstring>
 8 
 9 #include<algorithm>
10 
11 #include<iostream>
12 
13 #include<vector>
14 
15 #include<map>
16 
17 #include<set>
18 
19 #include<queue>
20 
21 #include<string>
22 
23 #define inf 1000000000
24 
25 #define maxn 2000000+5
26 
27 #define maxm 500+100
28 
29 #define eps 1e-10
30 
31 #define ll long long
32 
33 #define pa pair<int,int>
34 
35 #define for0(i,n) for(int i=0;i<=(n);i++)
36 
37 #define for1(i,n) for(int i=1;i<=(n);i++)
38 
39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
40 
41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
42 
43 #define mod 1000000007
44 
45 using namespace std;
46 
47 inline int read()
48 
49 {
50 
51     int x=0,f=1;char ch=getchar();
52 
53     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
54 
55     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
56 
57     return x*f;
58 
59 }
60 int n,m,a[maxn],b[maxn],next[maxn],ans,tot;
61 
62 int main()
63 
64 {
65 
66     freopen("input.txt","r",stdin);
67 
68     freopen("output.txt","w",stdout);
69 
70     n=read();m=read();int x=-1;
71     for1(i,m)a[((x+=read())%=n)+1]++;
72     for1(i,n)a[n+i]=a[i];
73     for1(i,n)b[i]=read();
74     int j=0;
75     for2(i,2,n)
76     {
77         while(j&&b[j+1]!=b[i])j=next[j];
78         if(b[j+1]==b[i])j++;
79         next[i]=j;
80     }
81     j=0;
82     for1(i,2*n-1)
83     {
84         while(j&&b[j+1]!=a[i])j=next[j];
85         if(b[j+1]==a[i])j++;
86         if(j==n)tot++,ans=1-i+n+n,j=next[j];
87     }
88     if(tot!=1){printf("Cannot determine!\n");printf("%d\n",tot);}else printf("%d\n",(ans-1)%n+1);
89 
90     return 0;
91 
92 } 
View Code

 

posted @ 2014-11-24 11:26  ZYF-ZYF  Views(229)  Comments(0Edit  收藏  举报