代码改变世界

7月29集训训练个人赛第五场

2013-07-29 10:58  bootstar  阅读(224)  评论(0编辑  收藏  举报

A Codeforces 126B

KMP。直接计算next数组就可以了,然后按照next数组的值直接判定是否存在一个子串长度满足条件即可。

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 const int maxn = 1000005;
 4 char src[maxn];
 5 int f[maxn];
 6 
 7 void getFail(char *src){
 8     f[1] = 0;
 9     int cur = 0;
10     for(int i = 2; src[i]; i ++){
11         while(src[cur + 1] != src[i] && cur) cur = f[cur];
12         if(src[cur + 1]==src[i]) f[i] = ++ cur;
13         else f[i] = cur = 0;
14     }
15 }
16 bool check(int len){
17     int x = 0;
18     for(int i = 1; src[i]; i ++){
19         x = x + (f[i] >= len);
20     }
21     if(x < 2) return false;
22     return true;
23 }
24 int main(){
25     //freopen("test.in", "r", stdin);
26     for(;scanf("%s", src + 1)!=EOF;){
27         memset(f, 0, sizeof(f));
28         getFail(src);
29         int len = strlen(src+1);
30         int ans = f[len];
31         if(ans == 0){
32                     printf("Just a legend\n");
33                     continue;
34         }
35         if(len%(len - ans) == 0 && (len/(len - ans) > 2)){
36             for(int i = 1; i <= len - 2*(len - ans); i ++)
37                 putchar(src[i]);
38             putchar('\n');
39             continue;
40         }
41 
42         for(;!check(ans) && ans; ans = f[ans]);
43         if(ans == 0){
44             printf("Just a legend\n");
45         }
46         else{
47             for(int i = 1; i <= ans; i ++){
48                 putchar(src[i]);
49             }
50             putchar('\n');
51         }
52     }
53     return 0;
54 }
View Code

 

B Codeforces 315E

树状数组或者线段树。问题是统计序列的每个子序列的要写的序列的个数。直接看代码吧,表示已经不晓得怎么解释了。或者去看官方题解好了。。http://codeforces.com/blog/entry/7905

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <iostream>
 4 using namespace std;
 5 #define MOD 1000000007
 6 const int maxn = 1000005;
 7 typedef long long LL;
 8 LL A[maxn], B[maxn];
 9 
10 #define LOWBIT(x) ((x)&(-x))
11 void add(int x, LL y){
12     while(x < maxn){
13         A[x] = (A[x] + y)%MOD;
14         x += LOWBIT(x);
15     }
16 }
17 LL getSum(int x){
18     LL sum = 0;
19     while(x){
20         sum = (sum + A[x])%MOD;
21         x -= LOWBIT(x);
22     }
23     return sum%MOD;
24 }
25 int main(){
26     int n, x;
27     cin>>n;
28     LL ans = 0;
29     for(int i = 1; i <= n; i ++){
30         cin>>x;
31         LL cur = getSum(x);
32         cur = (cur*x+x)%MOD;
33         ans = (ans + cur - B[x])%MOD;
34         add(x, cur - B[x]);
35         B[x] = cur;
36     }
37     cout<<(ans%MOD+MOD)%MOD<<endl;
38     return 0;
39 }
View Code

 

C Codeforces 242E

线段树的裸题。可以将和拆分成二进制位计算就可以了,剩余的就是赤果果的线段树了。

 

  1 #include <stdio.h>
  2 #include <string.h>
  3 typedef long long LL;
  4 const int maxn = 100005;
  5 const int SIZE = 21;
  6 
  7 #define lson(c) (c<<1)
  8 #define rson(c) (c<<1|1)
  9 #define mid(l, r) ((l+r)/2)
 10 
 11 struct Tree{
 12     int f[maxn*4][SIZE];
 13     int s[maxn*4];
 14     void push_up(int c){
 15         int l = lson(c);
 16         int r = rson(c);
 17         for(int i = 0; i < SIZE; i ++){
 18             f[c][i] = f[l][i] + f[r][i];
 19         }
 20         s[c] = 0;
 21     }
 22     void push_down(int c, int l, int r){
 23         int ls = lson(c);
 24         int rs = rson(c);
 25         int t = s[c];
 26         int md = mid(l, r);
 27         if(s[c]==0) return;
 28 
 29         for(int i = 0; i < SIZE; i ++, t >>= 1){
 30             if(t&1){
 31                 f[ls][i] = (md - l + 1) - f[ls][i];
 32                 f[rs][i] = (r - md) - f[rs][i];
 33             }
 34         }
 35                 s[ls]^=s[c];
 36                 s[rs]^=s[c];
 37     }
 38     void build(int c, int l, int r){
 39         s[c] = 0;
 40         if(l==r){
 41             int x; scanf("%d", &x);
 42             for(int i = 0; i < SIZE; i ++){
 43                 f[c][i] = x&1; x>>=1;
 44             }
 45             return;
 46         }
 47         build(lson(c), l, mid(l, r));
 48         build(rson(c), mid(l, r) + 1, r);
 49         push_up(c);
 50     }
 51     void update(int c, int l, int r, int lp, int rp, int x){
 52         if(lp <= l && rp >= r){
 53             s[c] ^= x;
 54             for(int i = 0; i < SIZE; i ++, x>>=1){
 55                 if(x&1) f[c][i] = (r - l + 1) - f[c][i];
 56             }
 57             return ;
 58         }
 59         push_down(c, l, r);
 60         int md = mid(l, r);
 61         if(rp <= md) update(lson(c), l, md, lp, rp, x);
 62         else if(lp > md) update(rson(c), md + 1, r, lp, rp, x);
 63         else{
 64             update(lson(c), l, md, lp, md, x);
 65             update(rson(c), md + 1, r, md + 1, rp, x);
 66         }
 67         push_up(c);
 68     }
 69     void query(int c, int l, int r, int lp, int rp, int ans[]){
 70         if(lp <= l && rp >= r){
 71             for(int i = 0; i < SIZE; i ++){
 72                 ans[i] += f[c][i];
 73             }
 74             return;
 75         }
 76         push_down(c, l, r);
 77         int md = mid(l, r);
 78         if(rp <= md) query(lson(c), l, md, lp, rp, ans);
 79         else if(lp > md) query(rson(c), md + 1, r, lp, rp, ans);
 80         else{
 81             query(lson(c), l, md, lp, md, ans);
 82             query(rson(c), md + 1, r, md + 1, rp, ans);
 83         }
 84         push_up(c);
 85     }
 86 }tree;
 87 
 88 int main(){
 89     //freopen("test.in", "r", stdin);
 90     for(int n, m; scanf("%d", &n)!=EOF;){
 91         tree.build(1, 1, n);
 92         int ans[32];
 93         scanf("%d", &m);
 94         for(int i = 1, l, r, t; i <= m; i ++){
 95             scanf("%d%d%d", &t, &l, &r);
 96             if(t==1){
 97                 memset(ans, 0, sizeof(ans));
 98                 tree.query(1, 1, n, l, r, ans);
 99                 LL answer = 0;
100                 for(int i = 0, x = 1; i < SIZE; i ++){
101                     answer = answer + (LL)x * ans[i];
102                     x<<=1;
103                 }
104                 printf("%I64d\n", answer);
105             }
106             else{
107                 int x;
108                 scanf("%d", &x);
109                 tree.update(1, 1, n, l, r, x);
110             }
111         }
112     }
113     return 0;
114 }
View Code

 

D Codeforces 11D

状态压缩,dp[mask][i]表示遍历mask中的所有点并以最小标号的点为起点,以i点为终点的简单路径的个数。集合与路径上的动态规划http://codeforces.com/blog/entry/337

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 using namespace std;
 5 const int maxn = 20;
 6 typedef long long LL;
 7 int g[maxn][maxn];
 8 LL d[1<<maxn][maxn];
 9 LL ans;
10 
11 inline bool bit(int i, int mask){
12     return mask&(1<<i);
13 }
14 inline int first(int mask){
15     int r;
16     for(r = 0; !(mask &(1<<r)); r ++);
17     return r;
18 }
19 inline int count(int mask){
20     int c = 0;
21     for(; mask; mask>>=1){
22         c += (mask&1);
23     }
24     return c;
25 }
26 LL dfs(int mask, int ep, int n){
27     int cnt = count(mask), sp = first(mask); LL sum = 0;
28     if(d[mask][ep]>=0) return d[mask][ep];
29     for(int p = first(mask); p < n; p ++){
30         if(p != ep && bit(p, mask) && g[p][ep] && (cnt==2||p != sp)){
31             sum = sum + dfs(mask^(1<<ep), p, n);
32         }
33     }
34     if(cnt > 2 && g[ep][sp])
35         ans += sum;
36     return (d[mask][ep] = sum);
37 }
38 int main(){
39     //freopen("test.in", "r", stdin);
40     for(int n, m; scanf("%d%d", &n, &m)!=EOF; ){
41         memset(g, 0, sizeof(g));
42         memset(d, -1, sizeof(d));
43         for(int i = 1, x, y; i <= m; i ++){
44             scanf("%d%d", &x, &y);
45             x --, y --;
46             g[x][y] = g[y][x] = 1;
47         }
48         int mask = 1<<n;
49         ans = 0;
50         for(int i = 0; i < n; i ++)
51             d[1<<i][i] = 1;
52         for(int i = 1; i < mask; i ++){
53             if(count(i)>1){
54                 int sp = first(i);
55                 for(int j = sp; j < n; j ++){
56                     if(bit(j, i) && g[sp][j]){
57                         dfs(i, j, n);
58                     }
59                 }
60             }
61         }
62         printf("%I64d\n", ans/2);
63     }
64 
65     return 0;
66 }
View Code

 

E POJ 1285

水题。求多重组合,母函数或者DP搞。母函数就很直接了,每一种选取的个数为0-a[i],所以直接套模板就是了。母函数的相关资料: http://www.wutianqi.com/?p=596

DPdp[i][j]表示从前i重物品中选取j件的表示方法,所以dp[i][j] = sigma(dp[i-1][j-x]) 其中x <= a[i],a[i]表示第i件物品的个数。

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 typedef long long LL;
 4 int cnt[55];
 5 LL A[55], B[55];
 6 
 7 int findNext(int c){
 8     for(int i = c + 1; i <= 51; i ++){
 9         if(cnt[i]) return i;
10     }
11     return -1;
12 }
13 
14 void process(){
15     memset(A, 0, sizeof(A));
16     memset(B, 0, sizeof(B));
17     int c, r = 0;
18     c = findNext(0);
19     for(int i = 0; i <= cnt[c]; i ++){
20         A[i] = 1;
21     }
22     r = cnt[c];
23     while((c = findNext(c))!=-1){
24         for(int i = 0; i <= r; i ++){
25             for(int j = 0; j <= cnt[c]; j ++){
26                 B[i+j] += A[i];
27             }
28         }
29         r += cnt[c];
30         for(int i = 0; i <= r; i ++){
31             A[i] = B[i], B[i] = 0;
32         }
33     }
34 }
35 
36 int main(){
37     int n, m;
38     for(int kcas = 1;scanf("%d%d", &n, &m)!=EOF, n||m; kcas ++){
39         memset(cnt, 0, sizeof(cnt));
40         for(int i = 1; i <= n; i ++){
41             int d; scanf("%d", &d);
42             cnt[d] ++;
43         }
44         process();
45         printf("Case %d:\n", kcas);
46         for(int i = 1; i <= m; i ++){
47             int d; scanf("%d", &d);
48             printf("%I64d\n", A[d]);
49         }
50     }
51     return 0;
52 }
View Code

 

F Codeforces 146E

DP 首先考虑到为lucky的数字只有1300多个,这样就可以DP了。首先统计出不同lucky数字的个数,以及每个lucky出现的次数,排个序,然后dp[i][j]表示从前ilucky数中选取j个的选择办法, dp[i][j] = dp[i-1][j] + c[i] * dp[i-1][j-1],其中c[i]表示第ilucky出现的次数。然后枚举选择lucky数的个数,答案就是sigma(dp[l][x] * C[s][k-x]),其中l表示lucky数的不同个数,s表示非lucky数的个数。

 

 1 #include <stdio.h>
 2 #include <map>
 3 #include <string.h>
 4 #include <algorithm>
 5 using namespace std;
 6 #define maxn 1500
 7 typedef long long LL;
 8 const LL mod = 1000000007;
 9 LL dp[maxn][maxn], C[100005];
10 map<int, int> hash;
11 
12 bool check(int a){
13     for(;a; a/=10){
14         if(a%10!=4&&a%10!=7) return false;
15     }
16     return true;
17 }
18 
19 void extgcd(LL a, LL b, LL&g, LL&x, LL&y){
20     if(b==0){
21         g = a, x = 1, y = 0; return;
22     }
23     extgcd(b, a%b, g, y, x);
24     y -= a/b*x;
25 }
26 
27 LL inv(LL a){
28     LL g, x, y;
29     extgcd(a, mod, g, x, y);
30     return (x + mod)%mod;
31 }
32 int main(){
33     for(int n, k; scanf("%d%d", &n, &k)!=EOF; ){
34         hash.clear();
35         int nl = 0, nu = 0;
36         for(int i = 1, x; i <= n; i ++){
37             scanf("%d", &x);
38             if(check(x)) {
39                 if(hash.count(x)==0){
40                     hash.insert(make_pair(x, 1));
41                     nl ++;
42                 }
43                 else hash[x] ++;
44             }
45             else nu ++;
46         }
47         dp[0][0] = 1;
48         int l = 1;
49         for(map<int, int>::iterator it = hash.begin(); it != hash.end(); it ++){
50             dp[l][0] = 1;
51             for(int j = 1; j <= l; j ++){
52                 dp[l][j] = (dp[l-1][j] + (it->second) * dp[l-1][j-1]%mod)%mod;
53             }
54             l ++;
55         }
56         memset(C, 0, sizeof(C));
57         C[0] = 1;
58         for(int i = 0; i < nu; i ++){
59             C[i + 1] = (C[i] * (nu - i)%mod)*inv(i+1)%mod;
60         }
61         LL ans = 0;
62         for(int x = 0; x <= k && x <= hash.size(); x ++){
63             ans = (ans + dp[nl][x] * C[k-x]%mod)%mod;
64         }
65         printf("%I64d\n", ans);
66     }
67     return 0;
68 }
View Code