agc031

T1 题意:给你一个串,求所有子序列个数,满足没有相同字符。1e5,2s。

解:考虑一个合法的子序列。其中每个字母的出现位置都有(出现次数)种选择。还可以不选,要 + 1。

然后乘起来就做完了。如果变成子串的话更简单,每个位置为开头的长度不会超过26,直接暴力。本质不同子串就开个hash池判重。

本质不同子序列......不会。

 1 #include <bits/stdc++.h>
 2 
 3 const int N = 100010, MO = 1e9 + 7;
 4 
 5 char str[N];
 6 int bin[26];
 7 
 8 int main() {
 9     int n;
10     scanf("%d", &n);
11     scanf("%s", str);
12     for(int i = 0; i < n; i++) {
13         bin[str[i] - 'a']++;
14     }
15     int ans = 1;
16     for(int i = 0; i < 26; i++) {
17         ans = 1ll * ans * (bin[i] + 1) % MO;
18     }
19     printf("%d", (ans + MO - 1) % MO);
20 
21     return 0;
22 }
AC代码

T2 题意:给你一个序列,可以若干次选择两个相同的数字,使其之间的数字全部变成这个数字。求最终可能的序列总数。2e5,2s。

解:发现选出来的序列一定是一些相离的,所以可以DP,设f[i]表示前i位可能的方案总数。那么第i位可能和前面任一个相同的数匹配,f[i] += f[j - 1]。

同时也可能不匹配,相当于自己跟自己匹配。我们要对所有ai等于一个数的DP值求和,直接开个桶。

发现有连续相同的数的时候会挂,把它们缩起来。

 1 #include <bits/stdc++.h>
 2 
 3 typedef long long LL;
 4 const int N = 200010, MO = 1e9 + 7;
 5 
 6 int a[N], bin[N], f[N];
 7 
 8 int main() {
 9 
10     int n;
11     scanf("%d", &n);
12     for(int i = 1; i <= n; i++) {
13         scanf("%d", &a[i]);
14         if(a[i] == a[i - 1]) {
15             i--;
16             n--;
17         }
18     }
19     f[0] = 1;
20     for(int i = 1; i <= n; i++) {
21         (bin[a[i]] += f[i - 1]) %= MO;
22         f[i] = bin[a[i]];
23     }
24     printf("%d", f[n]);
25 
26     return 0;
27 }
AC代码

T3 题意:求一个1 ~ 2n的排列,满足第一个数是A,最后一个数是B,且相邻两个数的二进制只有一位不同。17,2s。

解:猜一下结论,如果A和B二进制下不同的位数有偶数个,那么一定无解。其余的有解。

因为有个头尾的限制,所以我们直接暴力分治。

每次讨论A和B最高位是否相同。相同的话就先把最高位变一下填2n-1个,然后变回来填后面的。

不同的话就前2n-1个最高位从A,后面最高位从B。

  1 /**
  2  * There is a start and there is no end in the space. ---Infinity.
  3  * It ruins and goes though there is also a start in stars. ---Finite.
  4  * Only the man who has wisdom can read the most foolish one from the history.
  5  * Fishes living in the sea doesn't know the life in the land.
  6  * It also ruins and goes if they have wisdom.
  7  * It funnier that man exceeds the speed of light than fish start living in the land.
  8  * It can be said that this is an final ultimatum from the god to the people who can fight.
  9  *
 10  * Steins;Gate
 11  */
 12 
 13 #include <bits/stdc++.h>
 14 
 15 const int N = 150000;
 16 
 17 int n, A, B, p[N], top, now, lm, same, dt;
 18 
 19 inline void out(int x) {
 20     for(int i = 0; i < n; i++) {
 21         printf("%d", (x >> i) & 1);
 22     }
 23     return;
 24 }
 25 
 26 inline int cal(int x) {
 27     int ans = 0;
 28     while(x) {
 29         ans++;
 30         x -= x & (-x);
 31     }
 32     return ans;
 33 }
 34 
 35 inline int Abs(int x) {
 36     return x < 0 ? -x : x;
 37 }
 38 
 39 inline int First(int x) {
 40     for(int i = n - 1; i >= 0; i--) {
 41         if((x >> i) & 1) return 1 << i;
 42     }
 43     return 0;
 44 }
 45 
 46 void solve(int n, int l, int r, int a, int b) {
 47     if(n == 1) {
 48         p[l] = a;
 49         p[r] = b;
 50         return;
 51     }
 52     int mid = (l + r) >> 1, nexlm = (1 << (n - 1)) - 1;
 53     if(((a >> (n - 1)) & 1) == ((b >> (n - 1)) & 1)) {
 54         solve(n - 1, mid + 1, r, a & nexlm, b & nexlm);
 55         if((a >> (n - 1)) & 1) {
 56             for(int i = mid + 1; i <= r; i++) {
 57                 p[i] |= 1 << (n - 1);
 58             }
 59             p[l] = p[mid + 1];
 60             solve(n - 1, l + 1, mid + 1, a & nexlm, p[mid + 2] & nexlm);
 61         }
 62         else {
 63             p[l] = p[mid + 1];
 64             solve(n - 1, l + 1, mid + 1, a & nexlm, p[mid + 2] & nexlm);
 65             for(int i = l + 1; i <= mid + 1; i++) {
 66                 p[i] |= (1 << (n - 1));
 67             }
 68         }
 69     }
 70     else {
 71         solve(n - 1, l, mid, a & nexlm, (b & nexlm) ^ 1);
 72         if((a >> (n - 1)) & 1) {
 73             for(int i = l; i <= mid; i++) {
 74                 p[i] |= 1 << (n - 1);
 75             }
 76             solve(n - 1, mid + 1, r, p[mid] & nexlm, b & nexlm);
 77         }
 78         else {
 79             solve(n - 1, mid + 1, r, p[mid] & nexlm, b & nexlm);
 80             for(int i = mid + 1; i <= r; i++) {
 81                 p[i] |= 1 << (n - 1);
 82             }
 83         }
 84     }
 85     return;
 86 }
 87 
 88 int main() {
 89 
 90     scanf("%d%d%d", &n, &A, &B);
 91     lm = (1 << n) - 1, dt = A ^ B, same = dt ^ lm;
 92 
 93     if((cal(dt) & 1) == 0) {
 94         puts("NO");
 95     }
 96     else {
 97         puts("YES");
 98         solve(n, 0, lm, A, B);
 99         for(int i = 0; i <= lm; i++) {
100             //out(p[i]); printf(" ");
101             printf("%d ", p[i]);
102             //puts("");
103         }
104     }
105     return 0;
106 }
AC代码

T4 题意:给定两个排列a和b,定义f(a, b)是一个排列,满足第ai个位置上的数是bi。定义A为一个序列,每个元素是一个排列,且A1 = a, A2 = b, Ai = f(Ai-2, Ai-1),求Ak。10w,1e9,2s。

解:神仙...

对于两个排列a和b,定义ab[i] = a[b[i]], a-1[a[i]] = i。于是我们把A的前几项写出来,然后瞎搞一通,就能发现一个奇妙的规律orz...

直接上官方题解了。

我们把A的每一个元素拆成sts-1的形式。然后发现si+6 = siba-1b-1a,是个等比数列。然后t是6个一循环的。

于是我们求出ba-1b-1a的k / 6次方就做完了......注意到求一个排列的k次方只需找出每个元素所在的环,然后跳(k % 环长)步即可。

  1 #include <bits/stdc++.h>
  2 
  3 const int N = 100010;
  4 
  5 int a[N], b[N], c[N], d[N], A[N], n, k, vis[N], B[N], dis[N], C[N], D[N];
  6 int t1[2][N], t2[2][N], t3[2][N], ans[7][N];
  7 std::vector<int> v[N];
  8 
  9 inline int Find(int x, int t) {
 10     int loop = v[vis[x]].size() - 1;
 11     t = (t + dis[x]) % loop;
 12     return v[vis[x]][t];
 13 }
 14 
 15 int main() {
 16 
 17     scanf("%d%d", &n, &k);
 18     k--;
 19     for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
 20     for(int i = 1; i <= n; i++) scanf("%d", &b[i]);
 21 
 22     /// get A  c = b-1  d = a-1
 23     for(int i = 1; i <= n; i++) {
 24         c[b[i]] = i;
 25         d[a[i]] = i;
 26     }
 27     /*for(int i = 1; i <= n; i++) {
 28         printf("%d ", c[i]);
 29     }
 30     puts("");
 31     for(int i = 1; i <= n; i++) {
 32         printf("%d ", d[i]);
 33     }
 34     puts("");*/
 35     for(int i = 1; i <= n; i++) {
 36         A[i] = b[d[c[ a[i] ]]];
 37     }
 38     int t = k / 6;
 39     //printf("t = %d \n", t);
 40     /// get B = A^t
 41     for(int i = 1; i <= n; i++) {
 42         if(vis[i]) continue;
 43         /// !vis[i]
 44         int j = i;
 45         v[i].push_back(i);
 46         do {
 47             j = A[j];
 48             dis[j] = v[i].size();
 49             vis[j] = i;
 50             v[i].push_back(j);
 51         } while(j != i);
 52         dis[i] = 0;
 53     }
 54     for(int i = 1; i <= n; i++) {
 55         B[i] = t ? Find(i, t) : i;
 56     }
 57 
 58     /*printf("vis : \n");
 59     for(int i = 1; i <= n; i++) {
 60         printf("%d ", vis[i]);
 61     }
 62     puts("");
 63 
 64     printf("A : \n");
 65     for(int i = 1; i <= n; i++) {
 66         printf("%d ", A[i]);
 67     }
 68     puts("");*/
 69 
 70     memcpy(t1[0] + 1, B + 1, n * sizeof(int));
 71     memcpy(t1[1] + 1, B + 1, n * sizeof(int));
 72     memcpy(t2[0] + 1, a + 1, n * sizeof(int));
 73     memcpy(t2[1] + 1, b + 1, n * sizeof(int));
 74     for(int i = 1; i <= n; i++) {
 75         t3[0][t1[0][i]] = i;
 76         t3[1][t1[1][i]] = i;
 77     }
 78 
 79     for(int i = 1; i <= n; i++) {
 80         ans[0][i] = t1[0][t2[0][t3[0][i]]];
 81         ans[1][i] = t1[1][t2[1][t3[1][i]]];
 82     }
 83     t = k % 6;
 84     //printf("t = %d \n", t);
 85     for(int i = 2; i <= t; i++) {
 86         for(int j = 1; j <= n; j++) {
 87             ans[i][ans[i - 2][j]] = ans[i - 1][j];
 88         }
 89     }
 90 
 91     /*puts("");
 92     for(int i = 0; i <= 1; i++) {
 93         for(int j = 1; j <= n; j++) {
 94             printf("%d ", ans[i][j]);
 95         }
 96         puts("");
 97     }
 98     puts("");*/
 99 
100     for(int i = 1; i <= n; i++) {
101         printf("%d ", ans[t][i]);
102     }
103 
104     return 0;
105 }
AC代码

 

posted @ 2019-04-10 09:30  huyufeifei  阅读(282)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜