# Noip2015提高组解题报告

Day1

T1神奇的幻方

ε=(´ο｀*)))唉又想起没学OI的自己了..

 1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn = 60;
4 int a[maxn][maxn];
5 int n, x, y;
6
8     int x = 0, y = 1;
9     char ch = getchar();
10     while(!isdigit(ch)) {
11         if(ch == '-') y = -1;
12         ch = getchar();
13     }
14     while(isdigit(ch)) {
15         x = (x << 1) + (x << 3) + ch - '0';
16         ch = getchar();
17     }
18     return x * y;
19 }
20
21 int main() {
23     x = 1, y = n / 2 + 1;
24     a[x][y] = 1;
25     for(register int i = 2; i <= n * n; ++i) {
26         if(x == 1 && y != n) {
27             x = n, y += 1;
28             a[x][y] = i;
29         }
30         else if(x != 1 && y == n) {
31             x -= 1, y = 1;
32             a[x][y] = i;
33         }
34         else if(x == 1 && y == n) {
35             x += 1;
36             a[x][y] = i;
37         }
38         else if(x != 1 && y != n) {
39             if(!a[x - 1][y + 1]) {
40                 x -= 1, y += 1;
41                 a[x][y] = i;
42             }
43             else if(a[x - 1][y + 1]) {
44                 x += 1;
45                 a[x][y] = i;
46             }
47         }
48     }
49     for(register int i = 1; i <= n; ++i) {
50         for(register int j = 1; j <= n; ++j)
51             printf("%d ", a[i][j]);
52         printf("\n");
53     }
54     return 0;
55 }

T2信息传递

 1 #include<bits/stdc++.h>
2 #define ll long long
3 #define uint unsigned int
4 #define ull unsigned long long
5 using namespace std;
6 const int maxn = 200010;
7 const int inf = 1000000007;
8 int t, fa[maxn];
9 int dis[maxn], ans;
10 int n;
11
13     int x = 0, y = 1;
14     char ch = getchar();
15     while(!isdigit(ch)) {
16         if(ch == '-') y = -1;
17         ch = getchar();
18     }
19     while(isdigit(ch)) {
20         x = (x << 1) + (x << 3) + ch - '0';
21         ch = getchar();
22     }
23     return x * y;
24 }
25
26 int getfather(int x) {
27     if(x == fa[x]) return x;
28     int son_in_son = fa[x];
29     fa[x] = getfather(fa[x]);
30     dis[x] += dis[son_in_son];
31     return fa[x];
32 }
33
34 int main() {
35 //    freopen("message.in", "r", stdin);
36 //    freopen("message.out", "w", stdout);
38     for(register int i = 1; i <= n; ++i) fa[i] = i;
39     ans = inf;
40     for(register int i = 1; i <= n; ++i) {
42         int u = getfather(i), v = getfather(t);
43         if(u != v) {
44             fa[u] = v;
45             dis[i] = dis[t] + 1;
46         }
47         else ans = min(ans, dis[i] + dis[t] + 1);
48     }
49     printf("%d\n", ans);
50     return 0;
51 }

tarjan就更简单了，跑强连通分量，统计每个环中节点的大小，然后找最小的大小不为1环的就好了

 1 #include<bits/stdc++.h>
2 #define ll long long
3 #define uint unsigned int
4 #define ull unsigned long long
5 using namespace std;
6 const int maxn = 200010;
7 const int inf = 1000000007;
8 struct shiki {
9     int net, y;
10 }e[maxn << 1];
11 int lin[maxn], len = 0;
12 int dfn[maxn], low[maxn];
13 int num = 0, cnt = 0, top = 0;
14 int c_num[maxn], s[maxn];
15 bool in_s[maxn];
16 int sum[maxn];
17 int n, t, ans;
18
20     int x = 0, y = 1;
21     char ch = getchar();
22     while(!isdigit(ch)) {
23         if(ch == '-') y = 1;
24         ch = getchar();
25     }
26     while(isdigit(ch)) {
27         x = (x << 1) + (x << 3) + ch - '0';
28         ch = getchar();
29     }
30     return x * y;
31 }
32
33 inline void insert(int xx, int yy) {
34     e[++len].y = yy;
35     e[len].net = lin[xx];
36     lin[xx] = len;
37 }
38
39 void tarjan(int x) {
40     dfn[x] = low[x] = ++num;
41     s[++top] = x, in_s[x] = 1;
42     for(int i = lin[x]; i; i = e[i].net) {
43         int to = e[i].y;
44         if(!dfn[to]) {
45             tarjan(to);
46             low[x] = min(low[x], low[to]);
47
48         }
49         else if(in_s[to]) low[x] = min(low[x], dfn[to]);
50     }
51     if(dfn[x] == low[x]) {
52         cnt++; int k;
53         do {
54             k = s[top--], in_s[k] = 0;
55             c_num[k] = cnt;
56         }while(x != k);
57     }
58 }
59
60 int main() {
61     memset(sum, 0, sizeof(sum));
63     for(register int i = 1; i <= n; ++i) {
65         insert(i, t);
66     }
67     for(register int i = 1; i <= n; ++i)
68         if(!dfn[i]) tarjan(i);
69     for(register int i = 1; i <= n; ++i)
70         sum[c_num[i]]++;
71     ans = inf;
72     for(register int i = 1; i <= cnt; ++i)
73         if(sum[i] != 1) ans = min(ans, sum[i]);
74     printf("%d\n", (ans != inf) ? ans : 1);
75     return 0;
76 }

T3斗地主

  1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn = 25;
4 const int inf = 1000000007;
5 int sum[maxn];
6 int T, n, ans;
7
9     int x = 0, y = 1;
10     char ch = getchar();
11     while(!isdigit(ch)) {
12         if(ch == '-') y = -1;
13         ch = getchar();
14     }
15     while(isdigit(ch)) {
16         x = (x << 1) + (x << 3) + ch - '0';
17         ch = getchar();
18     }
19     return x * y;
20 }
21
22 void dfs_kill(int x) {//出牌次数
23     /*
24     可以公开的情报：
25     出牌方式有火箭，炸弹，单牌，对牌，三不带，三带单，三带对，
26     顺子，连对，三顺, 四带二(且带的两张牌不要求相同）
27     */
28     if(x >= ans) return;
29     //顺子势力
30     int op = 0;//单顺
31     for(register int i = 3; i <= 14; ++i) {//2与双王不可用
32         if(sum[i] < 1) op = 0;//打断顺子
33         else {
34             op++;//长度加1
35             if(op >= 5) {
36                 for(register int j = i - op + 1; j <= i; ++j) sum[j]--;//出牌
37                 dfs_kill(x + 1);
38                 for(register int j = i - op + 1; j <= i; ++j) sum[j]++;//回溯
39             }
40         }
41     }
42     op = 0;//连对
43     for(register int i = 3; i <= 14; ++i) {
44         if(sum[i] < 2) op = 0;//打断连对
45         else {
46             op++;
47             if(op >= 3) {
48                 for(register int j = i - op + 1; j <= i; ++j) sum[j] -= 2;
49                 dfs_kill(x + 1);
50                 for(register int j = i - op + 1; j <= i; ++j) sum[j] += 2;
51             }
52         }
53     }
54     op = 0;//三顺
55     for(register int i = 3; i <= 14; ++i) {
56         if(sum[i] < 3) op = 0;
57         else {
58             op++;
59             if(op >= 2) {
60                 for(register int j = i - op + 1; j <= i; ++j) sum[j] -= 3;
61                 dfs_kill(x + 1);
62                 for(register int j = i - op + 1; j <= i; ++j) sum[j] += 3;
63             }
64         }
65     }
66     //带牌
67     for(register int i = 2; i <= 14; ++i) {//大小王不能带牌
68         if(sum[i] < 3) continue;//连三带都不行的
69         sum[i] -= 3;//大家都先搞三带
70         for(register int j = 2; j <= 16; ++j) {//三带一居然能带大小王??
71             if(sum[j] < 1 || j == i) continue;
72             sum[j]--;
73             dfs_kill(x + 1);
74             sum[j]++;
75         }
76         for(register int j = 2; j <= 14; ++j) {//三带二，大小王不算对子
77             if(sum[j] < 2 || j == i) continue;
78             sum[j] -= 2;
79             dfs_kill(x + 1);
80             sum[j] += 2;
81         }
82         sum[i] += 3;
83         if(sum[i] > 3) {//一些群众可以四带
84             sum[i] -= 4;
85             for(register int j = 2; j <= 15; ++j) {//带单牌之时,大小王算单牌
86                 if(sum[j] < 1 || j == i) continue;
87                 sum[j]--;
88                 for(register int k = 2; k <= 15; ++k) {
89                     if(sum[k] < 1 || (k == j && k != 15) || k == i) continue;
90                     sum[k]--;
91                     dfs_kill(x + 1);
92                     sum[k]++;
93                 }
94                 sum[j]++;
95             }
96             for(register int j = 2; j <= 14; ++j) {//带双牌之时,大小王不算对子
97                 if(sum[j] < 2 || j == i) continue;
98                 sum[j] -= 2;
99                 for(register int k = 2; k <= 14; ++k) {
100                     if(sum[k] < 2 || k == j || k == i) continue;
101                     sum[k] -= 2;
102                     dfs_kill(x + 1);
103                     sum[k] += 2;
104                 }
105                 sum[j] += 2;
106             }
107             sum[i] += 4;
108         }
109     }
110     //已经处理完了顺子，连对，三顺，三带一，三带二，四带二单，四带二对
111     //对于剩下的势力，显然可以一次性丢出去
112     for(register int i = 2; i <= 15; ++i) if(sum[i]) x++;
113     ans = min(ans, x);
114 }
115
116 int main() {
117 //    freopen("landlords.in", "r", stdin);
118 //    freopen("landlords.out", "w", stdout);
120     while(T--) {
121         memset(sum, 0, sizeof(sum));
122         ans = inf;
123         for(register int i = 1; i <= n; ++i) {
125             if(which == 0) sum[15]++;//大小王放在同一个位置
126             else if(which == 1) sum[14]++;//塞进一个A，因为A可以丢进顺子等组合且比较大，放在后面
127             else sum[which]++;
128         }
129         dfs_kill(0);
130         printf("%d\n", ans);
131     }
132     return 0;
133 }

Day2

 1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn = 50010;
4 int a[maxn];
5 int L, m, n;
6
8     int x = 0, y = 1;
9     char ch = getchar();
10     while(!isdigit(ch)) {
11         if(ch == '-') y = -1;
12         ch = getchar();
13     }
14     while(isdigit(ch)) {
15         x = (x << 1) + (x << 3) + ch - '0';
16         ch = getchar();
17     }
18     return x * y;
19 }
20
21 inline bool check(int x) {
22     int ans = 0, now = 0;
23     for(int i = 1; i <= n; ++i)
24         if(a[i] - now < x) ans++;
25         else now = a[i];
26     return ans <= m;
27 }
28
29 int main() {
31     for(int i = 1; i <= n; ++i) a[i] = read();
32     int l = 0, r = L;
33     while(l < r) {
34         int mid = l + r >> 1;
35         if(check(mid)) l = mid + 1;
36         else r = mid - 1;
37     }
38     if(!check(l)) l -= 1;
39     printf("%d\n", l);
40     return 0;
41 }

f[i, j, k, 0/1]表示A串取到了第i个字符，B串匹配了j个字符，使用了k个子串，第i个字符取或是不取

f[i][j][k][0] = (f[i-1][j][k][0] + f[i-1][j][k][1]) % mod

然后就简简单单地A题了

 1 #include<bits/stdc++.h>
2 using namespace std;
3 const int mod = 1000000007;
4 const int maxn = 1010;
5 const int maxm = 210;
6 int f[2][maxm][maxm][2];
7 char a[maxn], b[maxm];
8 int n, m, l, id = 1;
9
11     int x = 0, y = 1;
12     char ch = getchar();
13     while(!isdigit(ch)) {
14         if(ch == '-') y = -1;
15         ch = getchar();
16     }
17     while(isdigit(ch)) {
18         x = (x << 1) + (x << 3) + ch - '0';
19         ch = getchar();
20     }
21     return x * y;
22 }
23
24 int main() {
25 //    freopen("a.in", "r", stdin);
26 //    freopen("a.out", "w", stdout);
28     scanf("%s%s", a + 1, b + 1);
29     f[0][0][0][0] = f[1][0][0][0] = 1;
30     for(register int i = 1; i <= n; ++i) {
31         for(register int j = 1; j <= m; ++j)
32             for(register int k = 1; k <= l; ++k) {
33                 f[i&1][j][k][0] = (f[(i-1)&1][j][k][0] + f[(i-1)&1][j][k][1]) % mod;
34                 if(a[i] != b[j]) f[i&1][j][k][1] = 0;
35                 else f[i&1][j][k][1] = (f[(i-1)&1][j - 1][k][1] + (f[(i-1)&1][j - 1][k - 1][0] + f[(i-1)&1][j - 1][k - 1][1]) % mod) % mod;
36             }
37     }
38     printf("%d\n", (f[n & 1][m][l][0] + f[n & 1][m][l][1]) % mod);
39     return 0;
40 }

posted @ 2018-10-18 19:34  YuWenjue  阅读(512)  评论(0编辑  收藏