• CF1043


    找个下午打了场CF,结果被某uranus吊打......一千多名,过弱。

    T1,一眼二分了,后来发现题解是O(1)的hhh

    T2,题意精炼一下就是让你找一个串的循环节个数,直接n²枚举.....

    T3,给你一个ab串,你依次考虑每个前缀,选择reverse这个前缀或者不操作。输出方案使得最后的字典序最小。

    手玩一下就能发现,一定能构造出最小字典序,所有a都在b前面。

    具体操作是每个整段的结尾字符那里翻转。

    T4,给你10个1e5的排列,你需要从每个中提取连续的一段,使得这十段相同。求方案数。

    考虑KMP(????),就是我们线性的扫描第一个串,把它分成若干段十个串都相同的段,这样每段都可以拿公式计算。

    第一次交的时候一个中间变量没开long long挂了,太SB了。

    T5,题意有点长......就是给你n个人,你要把这n个人两两组队(就是n(n-1)/2次)各一次,每次解决两个任务a,b。

    每个人解决a,b问题都有个代价。组队时一人解决一道题,会自动选择总代价最小的解决方案,代价累加到两个人身上。

    问你这么多次下来每个人的总代价。

    把式子min(A + b, B + a)变形一下:min(b - a, B - A) + a + A

    然后就比较显然了.....显然可以用前缀和但是我SB的用了树状数组,不过复杂度一样。

    贴个考场代码吧。

     1 #include <bits/stdc++.h> 
     2 
     3 inline void read(int &x) {
     4     x = 0;
     5     char c = getchar();
     6     while(c < '0' || c > '9') {
     7         c = getchar();
     8     }
     9     while(c >= '0' && c <= '9') {
    10         x = (x << 3) + (x << 1) + c - 48;
    11         c = getchar();
    12     }
    13     return;
    14 }
    15 
    16 typedef long long LL;
    17 const int N = 300010;
    18 
    19 LL xi[N], yi[N], dt[N], X[N], ans[N];
    20 int n, pos[N]; 
    21 
    22 struct TA {
    23     LL ta[N];
    24     inline void add(int i, LL v) {
    25         for(; i <= n; i += i & (-i)) {
    26             ta[i] += v;
    27         }
    28         return;
    29     }
    30     inline LL getsum(int i) {
    31         LL ans = 0;
    32         for(; i > 0; i -= i & (-i)) {
    33             ans += ta[i];
    34         }
    35         return ans;
    36     }
    37     inline LL ask(int l, int r) {
    38         if(r < l) {
    39             return 0;
    40         }
    41         if(l <= 1) { 
    42             return getsum(r);
    43         }
    44         return getsum(r) - getsum(l - 1);
    45     }
    46 }cnt, sum;
    47 
    48 int main() {
    49     
    50     int m;
    51     scanf("%d%d", &n, &m);
    52     LL tot = 0;
    53     for(int i = 1; i <= n; i++) {
    54         scanf("%lld%lld", &xi[i], &yi[i]);
    55         dt[i] = yi[i] - xi[i];
    56         X[i] = dt[i];
    57         tot += xi[i];
    58     }
    59     
    60     std::sort(X + 1, X + n + 1);
    61     int xx = std::unique(X + 1, X + n + 1) - X - 1;
    62     
    63     
    64     for(int i = 1; i <= n; i++) {
    65         int p = std::lower_bound(X + 1, X + xx + 1, dt[i]) - X;
    66         pos[i] = p;
    67         cnt.add(p, 1);
    68         sum.add(p, dt[i]);
    69     }
    70     
    71     for(int i = 1; i <= n; i++) {
    72         int p = pos[i];
    73         ans[i] += sum.ask(1, p) - dt[i];
    74         ans[i] += cnt.ask(p + 1, n) * dt[i];
    75         ans[i] += tot - xi[i] + xi[i] * (n - 1);
    76     }
    77     for(int i = 1, x, y; i <= m; i++) {
    78         scanf("%d%d", &x, &y);
    79         ans[x] -= std::min(xi[x] + yi[y], xi[y] + yi[x]);
    80         ans[y] -= std::min(xi[x] + yi[y], xi[y] + yi[x]);
    81     }
    82     
    83     for(int i = 1; i <= n; i++) {
    84         printf("%lld ", ans[i]);
    85     }
    86     
    87     return 0;
    88 }
    AC代码

    当时境况比较尴尬,写出来时发现比赛刚结束68s......

    第一次交很SB的把long long用%d输出了。

    最后1104名......F题听说很有趣,以后来填。

    F 题意:给定n个数,从中选出尽量少的数,使得gcd为1。

    不存在方案输出-1。n,值域<=300000。

    解:正解是:有个结论,如果存在合法解,那么一定有一组合法解的个数不超过7。不会证...

    然后设f[i][j]表示选i个数,gcd为j的方案数。

    f[i][j] = C(sumj, i) - ∑f[i][j * d]

    然后求出一个最小的i使得f[i][1] > 0即可。

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 typedef long long LL;
     5 const int N = 300010, lm = 300000;
     6 const LL mo[] = {998244353, (LL)(1e9 + 7)};
     7 
     8 int sum[N], bin[N], n;
     9 LL f[10][N], nn[N], invn[N], inv[N], MO;
    10 
    11 inline LL C(int n, int i) {
    12     return nn[n] * invn[i] % MO * invn[n - i] % MO;
    13 }
    14 
    15 inline int cal(int turn) {
    16     MO = mo[turn];
    17     for(int i = 2; i <= lm; i++) {
    18         nn[i] = nn[i - 1] * i % MO;
    19         inv[i] = (MO - inv[MO % i]) * (MO / i) % MO;
    20         invn[i] = invn[i - 1] * inv[i] % MO;
    21     }
    22     for(int i = 1; i <= 7; i++) {
    23         for(int j = lm; j >= 1; j--) {
    24             if(sum[j] < i) {
    25                 continue;
    26             }
    27             f[i][j] = C(sum[j], i);
    28             for(int k = 2; k * j <= lm; k++) {
    29                 f[i][j] = (f[i][j] - f[i][j * k] + MO) % MO;
    30             }
    31             //printf("f %d %d = %d 
    ", i, j, f[i][j]);
    32         }
    33     }
    34     for(int i = 1; i <= 7; i++) {
    35         if(f[i][1]) {
    36             return i;
    37         }
    38     }
    39     return -1;
    40 }
    41 
    42 int main() {
    43     nn[0] = inv[0] = invn[0] = 1;
    44     nn[1] = inv[1] = invn[1] = 1;
    45     int n;
    46     scanf("%d", &n);
    47     for(int i = 1, x; i <= n; i++) {
    48         scanf("%d", &x);
    49         bin[x]++;
    50     }
    51     for(int i = 1; i <= lm; i++) {
    52         for(int j = 1; j * i <= lm; j++) {
    53             sum[i] += bin[i * j];
    54         }
    55     }
    56 
    57     int a = cal(0), b = cal(1);
    58     int ans = std::min(a, b);
    59     if(ans == -1) {
    60         printf("%d", std::max(a, b));
    61     }
    62     else {
    63         printf("%d", std::min(a, b));
    64     }
    65     return 0;
    66 }
    AC代码

    反演+二分解法:

    首先二分答案,然后用反演求:选出k个,gcd为1的方案数。如果大于0就可行。

     1 #include <bits/stdc++.h>
     2 
     3 const int N = 300010, MO = 998244353;
     4 
     5 int p[N], top, miu[N], bin[N], fac[N], inv[N], invn[N];
     6 bool vis[N];
     7 
     8 inline int C(int n, int m) {
     9     if(m > n || n < 0 || m < 0) return 0;
    10     return 1ll * fac[n] * invn[m] % MO * invn[n - m] % MO;
    11 }
    12 
    13 inline void getp(int n) {
    14     miu[1] = 1;
    15     for(int i = 2; i <= n; i++) {
    16         if(!vis[i]) {
    17             p[++top] = i;
    18             miu[i] = -1;
    19         }
    20         for(int j = 1; j <= top && i * p[j] <= n; j++) {
    21             vis[i * p[j]] = 1;
    22             if(i % p[j] == 0) {
    23                 miu[i * p[j]] = 0;
    24                 break;
    25             }
    26             miu[i * p[j]] = -miu[i];
    27         }
    28     }
    29     return;
    30 }
    31 
    32 inline int check(int k) {
    33     int ans = 0;
    34     for(int i = 1; i < N; i++) {
    35         (ans += miu[i] * C(bin[i], k)) %= MO;
    36         ans = (ans + MO) % MO;
    37     }
    38     return ans;
    39 }
    40 
    41 int main() {
    42     getp(N - 1);
    43     inv[0] = fac[0] = invn[0] = 1;
    44     inv[1] = fac[1] = invn[1] = 1;
    45     for(int i = 2; i < N; i++) {
    46         fac[i] = 1ll * fac[i - 1] * i % MO;
    47         inv[i] = 1ll * inv[MO % i] * (MO - MO / i) % MO;
    48         invn[i] = 1ll * invn[i - 1] * inv[i] % MO;
    49     }
    50     int n;
    51     scanf("%d", &n);
    52     for(int i = 1, x; i <= n; i++) {
    53         scanf("%d", &x);
    54         bin[x]++;
    55     }
    56     for(int i = 1; i < N; i++) {
    57         for(int j = i << 1; j < N; j += i) {
    58             (bin[i] += bin[j]) %= MO;
    59         }
    60     }
    61 
    62     int l = 1, r = n + 1;
    63     while(l < r) {
    64         int mid = (l + r) >> 1;
    65         if(check(mid)) {
    66             r = mid;
    67         }
    68         else {
    69             l = mid + 1;
    70         }
    71     }
    72     if(r == n + 1) printf("-1
    ");
    73     else printf("%d
    ", r);
    74     return 0;
    75 }
    AC代码
  • 相关阅读:
    this 指向 及 调用方式
    页面布局上 左 右底部
    Thread Safety线程安全
    sql查删更
    LinuxMysql命令操作数据库
    excel链接sharepoint 用于 Excel 的 Microsoft Power Query
    W7无法更新
    发票点数计算
    sharepoint OWA问题解决
    zend studio 做前端推荐安装的插件
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/9919073.html
Copyright © 2020-2023  润新知