• 【 2013 Multi-University Training Contest 3 】


    HDU 4622 Reincarnation

    枚举字符串的起点,构造后缀自动机,每次插入一个字符,就能统计得到当前不同字串的个数,预处理出所有的询问。

     1 #include<cstdio>
     2 #include<cstring>
     3 #define MAXN 2010
     4 #define MAXM 26
     5 int res[MAXN][MAXN];
     6 char str[MAXN];
     7 struct node {
     8     node *next[MAXM];
     9     node *pre;
    10     int step;
    11     int tot;
    12 } sam[MAXN << 1];
    13 node *root = &sam[0];
    14 int cnt, last;
    15 int ans;
    16 node &newNode() {
    17     sam[++cnt].tot = 0;
    18     memset(sam[cnt].next, 0, sizeof(sam[cnt].next));
    19     return sam[cnt];
    20 }
    21 void add(int idx, int step) {
    22     node &p = newNode();
    23     p.step = step;
    24     p.pre = &p;
    25     node *u = &sam[last];
    26     last = cnt;
    27     while (u && u->next[idx] == 0) {
    28         u->next[idx] = &p;
    29         p.tot += u->tot;
    30         u = u->pre;
    31     }
    32     if (!u) {
    33         p.pre = root;
    34     } else {
    35         node *q = u->next[idx];
    36         if (q->step == u->step + 1) {
    37             p.pre = q;
    38         } else {
    39             node &nq = newNode();
    40             memcpy(nq.next, q->next, sizeof(q->next));
    41             nq.step = u->step + 1;
    42             nq.pre = q->pre;
    43             q->pre = &nq;
    44             p.pre = &nq;
    45             for (; u && u->next[idx] == q; u = u->pre) {
    46                 u->next[idx] = &nq;
    47                 q->tot -= u->tot;
    48                 nq.tot += u->tot;
    49             }
    50         }
    51     }
    52     ans += p.tot;
    53 }
    54 int main() {
    55     int T;
    56     int i, j;
    57     int len;
    58     int q;
    59     scanf("%d", &T);
    60     while (T--) {
    61         scanf(" %s", str);
    62         len = strlen(str);
    63         for (i = 0; i < len; i++) {
    64             sam[0].pre = 0;
    65             sam[0].tot = 1;
    66             cnt = last = 0;
    67             ans = 0;
    68             memset(sam[cnt].next, 0, sizeof(sam[cnt].next));
    69             for (j = i; j < len; j++) {
    70                 add(str[j] - 'a', j - i + 1);
    71                 res[i][j] = ans;
    72             }
    73         }
    74         scanf("%d", &q);
    75         while (q--) {
    76             scanf("%d%d", &i, &j);
    77             printf("%d
    ", res[i - 1][j - 1]);
    78         }
    79     }
    80     return 0;
    81 }
    View Code

    HDU 4623 Crime

    dp[28][228]表示最后取的数,当前状态,可以得到的方案数。显然不可行。

    由于相邻的两个数必须互素,所以这两个数不会有相同的素因子。

    将1~n的数划分等价类,具有相同素因子的数属于同一个等价类。

    通过打表可以发现,最后取的数减少到15,状态数减少到1728000。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<vector>
      4 #include<map>
      5 #define MAXL 15
      6 #define MAXN 30
      7 #define MAXM 1728000
      8 using namespace std;
      9 vector<int> prime;
     10 vector<int> factor;
     11 map<int, int> mymap;
     12 vector<int> g[MAXL];
     13 bool vis[MAXN];
     14 int dp[MAXM][MAXL];
     15 int base[MAXN];
     16 int stand[MAXN];
     17 int arr[MAXN];
     18 int tot;
     19 bool isPrime(int n) {
     20     for (int i = 2; i < n; i++) {
     21         if (n % i == 0) {
     22             return false;
     23         }
     24     }
     25     return true;
     26 }
     27 int GCD(int x, int y) {
     28     return y ? GCD(y, x % y) : x;
     29 }
     30 int encrypt() {
     31     int res = 0;
     32     for (int i = 0; i < tot; i++) {
     33         res = res * base[i] + arr[i];
     34     }
     35     return res;
     36 }
     37 void decrypt(int val) {
     38     for (int i = tot - 1; i >= 0; i--) {
     39         arr[i] = val % base[i];
     40         val /= base[i];
     41     }
     42 }
     43 int main() {
     44     int T;
     45     int n, m;
     46     int i, j, k, l;
     47     int tmp;
     48     int ans;
     49     pair<int, int> head, cur;
     50     map<int, int>::iterator it;
     51     scanf("%d", &T);
     52     while (T--) {
     53         scanf("%d%d", &n, &m);
     54         mymap.clear();
     55         memset(vis, false, sizeof(vis));
     56         for (i = 1; i <= n; i++) {
     57             for (j = 1; j <= n; j++) {
     58                 if (i == j) {
     59                     continue;
     60                 }
     61                 if (GCD(i, j) != 1) {
     62                     break;
     63                 }
     64             }
     65             if (j > n) {
     66                 vis[i] = true;
     67                 mymap[1]++;
     68             }
     69         }
     70         prime.clear();
     71         for (i = 2; i <= n; i++) {
     72             if (isPrime(i)) {
     73                 prime.push_back(i);
     74             }
     75         }
     76         for (i = 1; i < (1 << prime.size()); i++) {
     77             tmp = 1;
     78             factor.clear();
     79             for (k = i, j = 0; k; k >>= 1, j++) {
     80                 if (k & 1) {
     81                     tmp *= prime[j];
     82                     factor.push_back(prime[j]);
     83                 }
     84             }
     85             if (tmp <= n && !vis[tmp]) {
     86                 for (j = 1; j <= n; j++) {
     87                     for (k = 0; k < (int) factor.size(); k++) {
     88                         if (j % factor[k] != 0) {
     89                             break;
     90                         }
     91                     }
     92                     if (k >= (int) factor.size()) {
     93                         l = j;
     94                         for (k = 0; k < (int) factor.size(); k++) {
     95                             while (l % factor[k] == 0) {
     96                                 l /= factor[k];
     97                             }
     98                         }
     99                         if (l == 1) {
    100                             vis[l] = true;
    101                             mymap[tmp]++;
    102                         }
    103                     }
    104                 }
    105             }
    106         }
    107         memset(dp, 0, sizeof(dp));
    108         tot = 0;
    109         for (it = mymap.begin(); it != mymap.end(); it++) {
    110             stand[tot] = (*it).first;
    111             arr[tot] = (*it).second;
    112             base[tot++] = (*it).second + 1;
    113         }
    114         l = encrypt();
    115         dp[l][0] = 1;
    116         for (i = 0; i < tot; i++) {
    117             g[i].clear();
    118             for (j = 0; j < tot; j++) {
    119                 if (GCD(stand[i], stand[j]) == 1) {
    120                     g[i].push_back(j);
    121                 }
    122             }
    123         }
    124         for (i = l; i > 0; i--) {
    125             decrypt(i);
    126             for (j = 0; j < tot; j++) {
    127                 for (k = 0; k < (int) g[j].size(); k++) {
    128                     if (arr[g[j][k]] == 0) {
    129                         continue;
    130                     }
    131                     arr[g[j][k]]--;
    132                     l = encrypt();
    133                     dp[l][g[j][k]] += dp[i][j];
    134                     if (dp[l][g[j][k]] >= m) {
    135                         dp[l][g[j][k]] -= m;
    136                     }
    137                     arr[g[j][k]]++;
    138                 }
    139             }
    140         }
    141         ans = 0;
    142         for (i = 0; i < tot; i++) {
    143             ans += dp[0][i];
    144         }
    145         ans %= m;
    146         for (i = 0; i < tot; i++) {
    147             for (j = 1; j < base[i]; j++) {
    148                 ans *= j;
    149                 ans %= m;
    150             }
    151         }
    152         printf("%d
    ", ans);
    153     }
    154     return 0;
    155 }
    View Code

    HDU 4627 The Unsolvable Problem

    a+b=n,当a与b越接近,a*b越大。

    寻找最接近的两个互素的数,答案最大。

     1 #include<iostream>
     2 typedef long long LL;
     3 using namespace std;
     4 LL GCD(LL x, LL y) {
     5     return y ? GCD(y, x % y) : x;
     6 }
     7 int main() {
     8     int T;
     9     int n;
    10     int tmp;
    11     cin >> T;
    12     while (T--) {
    13         cin >> n;
    14         for (int i = n >> 1; i <= n; i++) {
    15             tmp = GCD(i, n - i);
    16             if (tmp == 1) {
    17                 cout << (LL) i * (n - i) / tmp << endl;
    18                 break;
    19             }
    20         }
    21     }
    22     return 0;
    23 }
    View Code

    HDU 4628 Pieces

    dp[i]表示状态为i的最少步数。对i枚举子集,dp[i]=min(dp[j]+dp[i^j])。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define MAXN 16
     5 #define oo 123456789
     6 using namespace std;
     7 char str[MAXN];
     8 int dp[1 << MAXN];
     9 bool isOK(int val) {
    10     char tmp[MAXN];
    11     int len = 0;
    12     for (int i = 0; val; val >>= 1, i++) {
    13         if (val & 1) {
    14             tmp[len++] = str[i];
    15         }
    16     }
    17     for (int i = 0, j = len - 1; i <= j; i++, j--) {
    18         if (tmp[i] != tmp[j]) {
    19             return false;
    20         }
    21     }
    22     return true;
    23 }
    24 int dfs(int x) {
    25     if (dp[x] != -1) {
    26         return dp[x];
    27     }
    28     int ans = oo;
    29     for (int i = (x - 1) & x; i; i = (i - 1) & x) {
    30         ans = min(ans, dfs(i) + dfs(x ^ i));
    31     }
    32     dp[x] = ans;
    33     return ans;
    34 }
    35 int main() {
    36     int T;
    37     int len;
    38     scanf("%d", &T);
    39     while (T--) {
    40         memset(dp, -1, sizeof(dp));
    41         scanf(" %s", str);
    42         len = strlen(str);
    43         dp[0] = 0;
    44         for (int i = 1; i < (1 << len); i++) {
    45             if (isOK(i)) {
    46                 dp[i] = 1;
    47             }
    48         }
    49         printf("%d
    ", dfs((1 << len) - 1));
    50     }
    51     return 0;
    52 }
    View Code

    HDU 4630 No Pain No Game

    枚举i,对于任意两个i的倍数,他们一定有约数i,有的等于它们的GCD,有的小于它们的GCD。

    对i的倍数,在数列出现的位置排序,相邻的两个看成一个线段,线段有一个权值i。

    问题转化为询问一个区间,能覆盖到的线段中,权值最大是多少。

    离线处理,对询问右端点排序从小到大排序,对所有线段右端点从小到大排序。

    每个询问[l,r],若线段[x,y]权值为val,对所有满足y<=r的线段插入线段树,插入的位置为x,权值为val。

    回答询问即求询问区间的最大值。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<vector>
      5 #define MAXN 50010
      6 #define MAXM 550000
      7 using namespace std;
      8 int arr[MAXN];
      9 int pos[MAXN];
     10 struct Query {
     11     int x, y;
     12     int index;
     13     friend bool operator<(Query a, Query b) {
     14         return a.y < b.y;
     15     }
     16 } ask[MAXN];
     17 struct node {
     18     int x, y;
     19     int val;
     20     friend bool operator<(node a, node b) {
     21         return a.y < b.y;
     22     }
     23 } p[MAXM];
     24 int tree[MAXN << 2];
     25 int ans[MAXN];
     26 void build(int L, int R, int rt) {
     27     tree[rt] = 0;
     28     if (L != R) {
     29         int mid = (L + R) >> 1;
     30         build(L, mid, rt << 1);
     31         build(mid + 1, R, rt << 1 | 1);
     32     }
     33 }
     34 inline void pushUp(int rt) {
     35     tree[rt] = max(tree[rt << 1], tree[rt << 1 | 1]);
     36 }
     37 void update(int x, int val, int L, int R, int rt) {
     38     if (L == R) {
     39         tree[rt] = max(tree[rt], val);
     40     } else {
     41         int mid = (L + R) >> 1;
     42         if (x <= mid) {
     43             update(x, val, L, mid, rt << 1);
     44         } else {
     45             update(x, val, mid + 1, R, rt << 1 | 1);
     46         }
     47         pushUp(rt);
     48     }
     49 }
     50 int query(int x, int y, int L, int R, int rt) {
     51     if (x <= L && R <= y) {
     52         return tree[rt];
     53     } else {
     54         int mid = (L + R) >> 1;
     55         int ans = 0;
     56         if (x <= mid) {
     57             ans = max(ans, query(x, y, L, mid, rt << 1));
     58         }
     59         if (y > mid) {
     60             ans = max(ans, query(x, y, mid + 1, R, rt << 1 | 1));
     61         }
     62         return ans;
     63     }
     64 }
     65 int main() {
     66     int T;
     67     int n, q;
     68     int i, j;
     69     int cnt;
     70     vector<int> tmp;
     71     scanf("%d", &T);
     72     while (T--) {
     73         scanf("%d", &n);
     74         for (i = 1; i <= n; i++) {
     75             scanf("%d", &arr[i]);
     76             pos[arr[i]] = i;
     77         }
     78         scanf("%d", &q);
     79         for (i = 0; i < q; i++) {
     80             scanf("%d%d", &ask[i].x, &ask[i].y);
     81             ask[i].index = i;
     82         }
     83         sort(ask, ask + q);
     84         cnt = 0;
     85         for (i = 1; i <= n; i++) {
     86             tmp.clear();
     87             for (j = i; j <= n; j += i) {
     88                 tmp.push_back(pos[j]);
     89             }
     90             sort(tmp.begin(), tmp.end());
     91             for (j = 1; j < (int) tmp.size(); j++) {
     92                 p[cnt].x = tmp[j - 1];
     93                 p[cnt].y = tmp[j];
     94                 p[cnt++].val = i;
     95             }
     96         }
     97         sort(p, p + cnt);
     98         build(1, n, 1);
     99         for (i = j = 0; i < q; i++) {
    100             for (; j < cnt && p[j].y <= ask[i].y; j++) {
    101                 update(p[j].x, p[j].val, 1, n, 1);
    102             }
    103             ans[ask[i].index] = query(ask[i].x, ask[i].y, 1, n, 1);
    104         }
    105         for (i = 0; i < q; i++) {
    106             printf("%d
    ", ans[i]);
    107         }
    108     }
    109     return 0;
    110 }
    View Code

    HDU 4631 Sad Love Story

    由于数据是随机的……

    用set保存点集,按x坐标排序。

    每次插入一个点后,从该位置沿x方向递增更新结果,当横坐标之差大于等于最近点对的时候,就跳出循环。

     1 #include<cstdio>
     2 #include<set>
     3 #include<iostream>
     4 typedef long long LL;
     5 #define MAXN 500010
     6 #define oo 123456789123456789LL
     7 using namespace std;
     8 struct Point {
     9     int x, y;
    10     Point(int _x = 0, int _y = 0) {
    11         x = _x;
    12         y = _y;
    13     }
    14     friend bool operator<(Point a, Point b) {
    15         if (a.x != b.x) {
    16             return a.x < b.x;
    17         } else {
    18             return a.y < b.y;
    19         }
    20     }
    21 };
    22 set<Point> myset;
    23 Point p[MAXN];
    24 inline LL dis2(Point a, Point b) {
    25     LL x = a.x - b.x;
    26     LL y = a.y - b.y;
    27     return x * x + y * y;
    28 }
    29 inline LL dis1(Point a, Point b) {
    30     LL x = a.x - b.x;
    31     return x * x;
    32 }
    33 int main() {
    34     int T;
    35     int n;
    36     int ax, bx, cx;
    37     int ay, by, cy;
    38     LL ans, res;
    39     set<Point>::iterator it, tmp;
    40     scanf("%d", &T);
    41     while (T--) {
    42         scanf("%d%d%d%d%d%d%d", &n, &ax, &bx, &cx, &ay, &by, &cy);
    43         p[0] = Point(bx % cx, by % cy);
    44         for (int i = 1; i < n; i++) {
    45             p[i] = Point((p[i - 1].x * (LL) ax + bx) % cx,
    46                     (p[i - 1].y * (LL) ay + by) % cy);
    47         }
    48         res = oo;
    49         ans = 0;
    50         myset.clear();
    51         myset.insert(p[0]);
    52         for (int i = 1; i < n; i++) {
    53             if (myset.count(p[i])) {
    54                 break;
    55             }
    56             myset.insert(p[i]);
    57             it = myset.find(p[i]);
    58             for (tmp = it, ++tmp; tmp != myset.end(); ++tmp) {
    59                 if (dis1(*it, *tmp) >= res) {
    60                     break;
    61                 } else {
    62                     res = min(res, dis2(*it, *tmp));
    63                 }
    64             }
    65             if (it != myset.begin()) {
    66                 for (tmp = it, --tmp;; --tmp) {
    67                     if (dis1(*it, *tmp) >= res) {
    68                         break;
    69                     } else {
    70                         res = min(res, dis2(*it, *tmp));
    71                     }
    72                     if (tmp == myset.begin()) {
    73                         break;
    74                     }
    75                 }
    76             }
    77             ans += res;
    78         }
    79         cout << ans << endl;
    80     }
    81     return 0;
    82 }
    View Code
  • 相关阅读:
    iOS开发之ImageView复用实现图片无限轮播
    IOS 通过脚本自动打包工具 webfrogs/xcode_shell
    (iOS)判断GPS坐标是否在中国
    如何轻松实现iOS9多任务管理器效果(iCarousel高级教程)
    有了Auto Layout,为什么你还是害怕写UITabelView的自适应布局?
    PID控制算法的C语言实现四 增量型PID的C语言实现
    PID控制算法的C语言实现三 位置型PID的C语言实现
    PID控制算法的C语言实现二 PID算法的离散化
    PID控制算法的C语言实现一 PID算法原理
    人生是一个连续的过程,没什么东西能影响人的一生,怎么选择不是问题。问题是每天都要努力 (转)
  • 原文地址:https://www.cnblogs.com/DrunBee/p/3225899.html
Copyright © 2020-2023  润新知