• 【 2013 Multi-University Training Contest 4 】


    HDU 4632 Palindrome subsequence

    dp[x][y]表示区间[x,y]构成回文串的方案数。

    若str[x]==str[y],dp[x][y]=dp[x+1][y]+dp[x][y-1]-dp[x+1][y-1]+(dp[x+1][y-1]+1)=dp[x+1][y]+dp[x][y-1]+1。

    若str[x]!=str[y],dp[x][y]=dp[x+1][y]+dp[x][y-1]-dp[x+1][y-1]。

     1 #include<cstdio>
     2 #include<cstring>
     3 #define MAXN 1010
     4 #define MOD 10007
     5 char str[MAXN];
     6 int dp[MAXN][MAXN];
     7 int dfs(int x, int y) {
     8     if (dp[x][y] == -1) {
     9         if (str[x] != str[y]) {
    10             dp[x][y] = dfs(x + 1, y) + dfs(x, y - 1) - dfs(x + 1, y - 1);
    11         } else {
    12             dp[x][y] = dfs(x + 1, y) + dfs(x, y - 1) + 1;
    13         }
    14     }
    15     dp[x][y] %= MOD;
    16     return dp[x][y];
    17 }
    18 int main() {
    19     int T;
    20     int ca = 1;
    21     int len;
    22     int i;
    23     scanf("%d", &T);
    24     while (T--) {
    25         memset(dp, -1, sizeof(dp));
    26         scanf(" %s", str);
    27         len = strlen(str);
    28         for (i = 0; i < len; i++) {
    29             dp[i][i] = 1;
    30         }
    31         for (i = 1; i < len; i++) {
    32             if (str[i] == str[i - 1]) {
    33                 dp[i - 1][i] = 3;
    34             } else {
    35                 dp[i - 1][i] = 2;
    36             }
    37         }
    38         printf("Case %d: %d
    ", ca++, (dfs(0, len - 1) + MOD) % MOD);
    39     }
    40     return 0;
    41 }
    View Code

    HDU 4633 Who's Aunt Zhang

    由Polya得到:

    本身到本身的置换有1种,k8+12+54

    沿着一个面的中心旋转90度有3种,k(1+1+3)*(1+1+3)+1+9

    沿着一个面的中心旋转270度有3种,k(1+1+3)*(1+1+3)+1+9

    沿着一个面的中心旋转180度有3种,k(2+2+5)*(2+2+5)+2+18

    沿着正方体的两个对顶点旋转120度有4种,k2+2+9+9+2+2

    沿着正方体的两个对顶点旋转240度有4种,k2+2+9+9+2+2

    沿着正方体的中心,与正方体任意两条对边的中点旋转180度有6种,k4+8+18+8

     1 #include<cstdio>
     2 #define MOD 10007
     3 int powmod(int a, int b) {
     4     int ans;
     5     for (ans = 1; b; b >>= 1) {
     6         if (b & 1) {
     7             ans *= a;
     8             ans %= MOD;
     9         }
    10         a *= a;
    11         a %= MOD;
    12     }
    13     return ans;
    14 }
    15 int ext_gcd(int a, int b, int &x, int &y) {
    16     int t, d;
    17     if (b == 0) {
    18         x = 1;
    19         y = 0;
    20         return a;
    21     }
    22     d = ext_gcd(b, a % b, x, y);
    23     t = x;
    24     x = y;
    25     y = t - a / b * y;
    26     return d;
    27 }
    28 
    29 int Invmod(int a, int n) {
    30     int x, y;
    31     if (ext_gcd(a, n, x, y) != 1)
    32         return -1;
    33     return (x % n + n) % n;
    34 }
    35 int main() {
    36     int T;
    37     int ca = 1;
    38     int n;
    39     int ans;
    40     scanf("%d", &T);
    41     while (T--) {
    42         scanf("%d", &n);
    43         ans = powmod(n, 8 + 12 + 54);
    44         ans += 6 * powmod(n, 20);
    45         ans += 3 * powmod(n, 38);
    46         ans += 8 * powmod(n, 26);
    47         ans += 6 * powmod(n, 38);
    48         printf("Case %d: %d
    ", ca++, ans % MOD * Invmod(24, MOD) % MOD);
    49     }
    50     return 0;
    51 }
    View Code

    HDU 4638 Group 

    询问区间最少可以组成多少段,连续的数可以组成一段。

    若x+1与x-1已经出现了,则加入x使得段数-1。

    若x+1与x-1都没有出现,则加入x使得段数+1。

    其他情况段数不变。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define MAXN 100010
     5 using namespace std;
     6 int n, m;
     7 bool vis[MAXN];
     8 int arr[MAXN];
     9 int tree[MAXN];
    10 int res[MAXN];
    11 int pos[MAXN];
    12 struct Ask {
    13     int x, y;
    14     int idx;
    15     friend bool operator<(Ask a, Ask b) {
    16         return a.x < b.x;
    17     }
    18 } ask[MAXN];
    19 inline int lowbit(int x) {
    20     return x & -x;
    21 }
    22 void update(int x, int val) {
    23     for (; x < MAXN; x += lowbit(x)) {
    24         tree[x] += val;
    25     }
    26 }
    27 int sum(int x) {
    28     int ans;
    29     for (ans = 0; x > 0; x -= lowbit(x)) {
    30         ans += tree[x];
    31     }
    32     return ans;
    33 }
    34 int main() {
    35     int T;
    36     int i, j;
    37     scanf("%d", &T);
    38     while (T--) {
    39         scanf("%d%d", &n, &m);
    40         for (i = 1; i <= n; i++) {
    41             scanf("%d", &arr[i]);
    42             pos[arr[i]] = i;
    43         }
    44         for (i = 0; i < m; i++) {
    45             scanf("%d%d", &ask[i].x, &ask[i].y);
    46             ask[i].idx = i;
    47         }
    48         sort(ask, ask + m);
    49         memset(tree, 0, sizeof(tree));
    50         memset(vis, false, sizeof(vis));
    51         for (i = 1; i <= n; i++) {
    52             vis[arr[i]] = true;
    53             if (vis[arr[i] - 1] && vis[arr[i] + 1]) {
    54                 update(i, -1);
    55             }
    56             if (!vis[arr[i] - 1] && !vis[arr[i] + 1]) {
    57                 update(i, 1);
    58             }
    59         }
    60         for (i = 0, j = 1; i < m; i++) {
    61             for (; j < ask[i].x; j++) {
    62                 if (vis[arr[j] + 1]) {
    63                     update(pos[arr[j] + 1], 1);
    64                 }
    65                 if (vis[arr[j] - 1]) {
    66                     update(pos[arr[j] - 1], 1);
    67                 }
    68                 vis[arr[j]] = false;
    69             }
    70             res[ask[i].idx] = sum(ask[i].y) - sum(ask[i].x - 1);
    71         }
    72         for (i = 0; i < m; i++) {
    73             printf("%d
    ", res[i]);
    74         }
    75     }
    76     return 0;
    77 }
    View Code

    HDU 4639 Hehe

    dp[i]表示以i结尾的方案数。

    dp[i]=dp[i-1]。

    若替换“hehe”,dp[i]+=dp[i-4]。

     1 #include<cstdio>
     2 #include<cstring>
     3 #define MAXN 100010
     4 #define MOD 10007
     5 int dp[MAXN];
     6 char str[MAXN];
     7 int main() {
     8     int T;
     9     int ca = 1;
    10     int len;
    11     int i;
    12     scanf("%d", &T);
    13     while (T--) {
    14         scanf(" %s", str + 1);
    15         len = strlen(str + 1);
    16         dp[0] = 1;
    17         for (i = 1; i <= len; i++) {
    18             dp[i] = dp[i - 1];
    19             if (i > 3 && str[i - 3] == 'h' && str[i - 2] == 'e'
    20                     && str[i - 1] == 'h' && str[i] == 'e') {
    21                 dp[i] += dp[i - 3];
    22             }
    23             dp[i] %= MOD;
    24         }
    25         printf("Case %d: %d
    ", ca++, dp[len]);
    26     }
    27     return 0;
    28 }
    View Code

     

    4640 Island and study-sister

    dp[i][j]表示访问了的地点压缩成i,最后访问的是j,它的最小花费。

    f[i][j]表示i个人,共同访问的地点压缩成j,它的最小花费。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<vector>
      4 #include<queue>
      5 #define MAXN 17
      6 #define MAXM 3
      7 #define oo 987654321
      8 using namespace std;
      9 int g[MAXN + 1][MAXN + 1];
     10 int dis[MAXN + 1][MAXN + 1];
     11 int dp[1 << MAXN][MAXN];
     12 int f[MAXM + 1][1 << MAXN];
     13 vector<int> island;
     14 void floyd(int n) {
     15     for (int k = 0; k < n; k++) {
     16         for (int i = 0; i < n; i++) {
     17             for (int j = 0; j < n; j++) {
     18                 dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
     19             }
     20         }
     21     }
     22 }
     23 bool getHelp() {
     24     for (int i = 0; i < (int) island.size(); i++) {
     25         if (dis[1][island[i]] >= oo) {
     26             return false;
     27         }
     28     }
     29     return true;
     30 }
     31 queue<pair<int, int> > q;
     32 int main() {
     33     int T;
     34     int ca = 1;
     35     int n, m, p;
     36     int x, y, val;
     37     int i, j, k;
     38     int vis;
     39     int ans;
     40     pair<int, int> head, tmp;
     41     scanf("%d", &T);
     42     while (T--) {
     43         scanf("%d%d", &n, &m);
     44         memset(g, 0x3f, sizeof(g));
     45         memset(dis, 0x3f, sizeof(dis));
     46         for (i = 0; i < m; i++) {
     47             scanf("%d%d%d", &x, &y, &val);
     48             x--;
     49             y--;
     50             g[x][y] = min(g[x][y], val);
     51             dis[x][y] = dis[y][x] = g[y][x] = g[x][y];
     52         }
     53         island.clear();
     54         scanf("%d", &p);
     55         for (i = 0; i < p; i++) {
     56             scanf("%d", &x);
     57             x--;
     58             island.push_back(x);
     59         }
     60         floyd(n);
     61         if (getHelp()) {
     62             memset(dp, 0x3f, sizeof(dp));
     63             dp[1][0] = 0;
     64             q.push(make_pair(1, 0));
     65             while (!q.empty()) {
     66                 head = q.front();
     67                 q.pop();
     68                 for (i = 0; i < n; i++) {
     69                     tmp.first = head.first | (1 << i);
     70                     tmp.second = i;
     71                     if (dp[tmp.first][tmp.second]
     72                             > dp[head.first][head.second]
     73                                     + g[head.second][tmp.second]) {
     74                         dp[tmp.first][tmp.second] = dp[head.first][head.second]
     75                                 + g[head.second][tmp.second];
     76                         q.push(tmp);
     77                     }
     78                 }
     79             }
     80             memset(f, 0x3f, sizeof(f));
     81             f[1][0] = 0;
     82             for (i = 1; i < (1 << n); i += 2) {
     83                 for (j = 0; j < n; j++) {
     84                     f[1][i] = min(f[1][i], dp[i][j]);
     85                 }
     86             }
     87             for (i = 2; i <= MAXM; i++) {
     88                 for (j = 1; j < (1 << n); j += 2) {
     89                     for (k = j; k >= 0; k = k ? (k - 1) & j : -1) {
     90                         f[i][j] = min(f[i][j],
     91                                 max(f[i - 1][k | 1], f[1][(j ^ k) | 1]));
     92                     }
     93                 }
     94             }
     95             vis = 0;
     96             for (i = 0; i < (int) island.size(); i++) {
     97                 vis |= 1 << island[i];
     98             }
     99             ans = oo;
    100             for (i = 0; i < (1 << n); i++) {
    101                 if ((i & vis) == vis) {
    102                     ans = min(ans, f[3][i]);
    103                 }
    104             }
    105         } else {
    106             ans = -1;
    107         }
    108         printf("Case %d: %d
    ", ca++, ans);
    109     }
    110     return 0;
    111 }
    View Code

    HDU 4642 Fliping game

    若右下角的数为1,则Alice必胜。Alice先把右下角变为0,无论Bob如何操作右下角的数都会变为1。

    若右下角的数为0,则Alice必败。Alice会把右下角的数变为1。

     1 #include<cstdio>
     2 int main() {
     3     int T;
     4     int n, m;
     5     int i, j, k;
     6     scanf("%d", &T);
     7     while (T--) {
     8         scanf("%d%d", &n, &m);
     9         for (i = 0; i < n; i++) {
    10             for (j = 0; j < m; j++) {
    11                 scanf("%d", &k);
    12             }
    13         }
    14         if (k) {
    15             puts("Alice");
    16         } else {
    17             puts("Bob");
    18         }
    19     }
    20     return 0;
    21 }
    View Code
  • 相关阅读:
    C++ 数组array与vector的比较
    C/C++头文件区别
    C/C++ 标准输入输出重定向
    C文件读写
    输入输出重定向
    【剑指offer26 二叉搜索树与双向链表】
    【剑指offer25 复杂链表的复制】
    【剑指offer23 二叉搜索树的后序遍历序列】
    【剑指offer22 从上往下打印二叉树 & 60 把二叉树打印成多行】
    【剑指offer21 栈的压入、弹出序列】
  • 原文地址:https://www.cnblogs.com/DrunBee/p/3231379.html
Copyright © 2020-2023  润新知