zoukankan      html  css  js  c++  java
  • Codeforces Round #305 (Div. 2)

    C. Mike and Frog

      题意:有一只青蛙和一朵花,分别高度为h1、h2,每浇一次水,h1=(x1*h1+y1)mod m,h2=(x2*h2+y2)mod m。求最少浇多少次后h1=a1,h2=a2?

      思路:先遍历m次找到第一次达到a1、a2的次数(若无,则为-1);再找到各自的循环节长度,然后枚举m次循环,判断能否符合题意。注意,可能在y2=0的时候,导致a2只出现一次,后面由于出现0而使得0对任意数取模都为0,则应当特别处理。

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int main()
     5 {
     6     int m, a1, x1, y1, a2, x2, y2;
     7     long long h1, h2;
     8     scanf("%d", &m);
     9     scanf("%I64d%d%d%d", &h1, &a1, &x1, &y1);
    10     scanf("%I64d%d%d%d", &h2, &a2, &x2, &y2);
    11     int len1=-1, len2=-1, st1=-1, st2=-1;
    12     for (int i = 1; i <= 2 * m; i++)
    13     {
    14         h1 = (x1*h1 + y1) % m;
    15         h2 = (x2*h2 + y2) % m;
    16         if (h1 == a1)
    17         {
    18             if (st1 == -1) st1 = i;
    19             else if (len1 == -1) len1 = i - st1;
    20         }
    21         if (h2 == a2)
    22         {
    23             if (st2 == -1) st2 = i;
    24             else if (len2 == -1) len2 = i - st2;
    25         }
    26         if (len1 != -1 && len2 != -1) break;
    27     }
    28     if (st1 == -1 || st2 == -1||(len1==-1&&len2==-1&&st1!=st2)) printf("-1
    ");
    29     else
    30     {
    31         bool flag = false;
    32         for (int i = 0; i <= m; i++)
    33         {
    34             if (len1 > 0 && len2 > 0)
    35             {
    36                 if ((1ll * st1 + 1ll * i * len1) >= st2 && (1ll * st1 + 1ll * i * len1 - st2) % len2 == 0)
    37                 {
    38                     printf("%I64d
    ", 1ll * st1 + 1ll * i * len1);
    39                     flag = true;
    40                     break;
    41                 }
    42             }
    43             else if (len1 > 0)
    44             {
    45                 if ((1ll * st1 + 1ll * i * len1) == st2)
    46                 {
    47                     printf("%I64d
    ", 1ll * st1 + 1ll * i * len1);
    48                     flag = true;
    49                     break;
    50                 }
    51             }
    52             else break;
    53         }
    54         if (!flag)
    55         {
    56             for (int i = 0; i <= m; i++)
    57             {
    58                 if (len1 > 0 && len2 > 0)
    59                 {
    60                     if ((1ll * st2 + 1ll * i * len2) >= st1 && (1ll * st2 + 1ll * i * len2 - st1) % len1 == 0)
    61                     {
    62                         printf("%I64d
    ", 1ll * st2 + 1ll * i * len2);
    63                         flag = true;
    64                         break;
    65                     }
    66                 }
    67                 else if (len2 > 0)
    68                 {
    69                     if ((1ll * st2 + 1ll * i * len2) == st1)
    70                     {
    71                         printf("%I64d
    ", 1ll * st2 + 1ll * i * len2);
    72                         flag = true;
    73                         break;
    74                     }
    75                 }
    76                 else break;
    77             }
    78         }
    79         if (!flag) printf("-1
    ");
    80     }
    81 
    82     return 0;
    83 }
    84 /*
    85 999983
    86 408725 408721
    87 1 1
    88 378562 294895
    89 984270 0
    90 499981500166
    91 */
    92 /*
    93 16
    94 1 0
    95 2 0
    96 1 2
    97 2 0
    98 -1
    99 */
    View Code

     D. Mike and Feet

      题意:有n只熊,每只熊有一个身高,他们站成一列。问区间长度为i时,所有区间最小值的最大值是多少?

      思路:用单调栈分别求出每只熊其向左、向右最远的大于等于它身高的熊的位置。设为Li、Ri,则在区间[Li,Ri]内,熊i的身高是最低的,显然ans[Ri-Li+1]=max(ans[Ri-Li+1],h[i]),显然的,在该区间内,长度为min(i-Li+1,Ri-i+1)~Ri-Li+1的区间长度的最小值就为h[i],而对于该区间内区间长度小于min(i-Li+1,Ri-i+1)的最小值,自然可由那些位置的熊的Lj、Rj来确定。而我们此处设置最大范围为该最小值h[i],那么之后我们可以用大区间的值来更新小区间的值。另做证明:如果len1>len2,但是ans[len1]>ans[len2],说明大区间最小值的最大值比小区间的最小值的最大值还大,说明存在某一个长度为len1的大区间,其最小值为v1,那么显然在该大区间内部去一个长度为len2的小区间,则该小区间内最小值至少大于等于v1。故可用大区间的值来更新小区间的值。

     1 #include<iostream>
     2 #include<stack>
     3 #include<algorithm>
     4 #include<cstdio>
     5 using namespace std;
     6 const int maxn = 200010;
     7 int v[maxn];
     8 int L_index[maxn];
     9 int R_index[maxn];
    10 int ans[maxn];
    11 int main()
    12 {  
    13     int n;
    14     scanf("%d", &n);
    15     for (int i = 1; i <= n; i++) scanf("%d", v + i);
    16     stack<int>stkL,stkR;
    17     for (int i = 1; i <= n; i++)
    18     {
    19         while (!stkL.empty() && v[i] <= v[stkL.top()]) stkL.pop();
    20         if (stkL.empty()) L_index[i] = 1;
    21         else L_index[i] = stkL.top() + 1;
    22         stkL.push(i);
    23     }
    24     for (int i = n; i>=1; --i)
    25     {
    26         while (!stkR.empty() && v[i] <= v[stkR.top()]) stkR.pop();
    27         if (stkR.empty()) R_index[i] = n;
    28         else R_index[i] = stkR.top() - 1;
    29         stkR.push(i);
    30     }
    31     for (int i = 1; i <= n; i++)
    32     {
    33         int len = R_index[i] - L_index[i] + 1;
    34         ans[len] = max(ans[len], v[i]);
    35     }
    36     for (int i = n-1; i >= 1; --i)
    37     {
    38         ans[i] = max(ans[i], ans[i + 1]);
    39     }
    40     for (int i = 1; i <= n; i++)
    41     {
    42         if (i > 1) printf(" ");
    43         printf("%d", ans[i]);
    44     }
    45     printf("
    ");
    46 
    47     return 0;
    48 }
    View Code

     E. Mike and Foam

      题意:有n杯啤酒,每杯啤酒的泡沫含量为ai。现在有一个空架子,q次询问,每次询问一杯啤酒的编号,如果其在架子上,则将其拿下,否则将其放上。并在每次询问后求架子上泡米含量互质的啤酒的对数。

      思路:先求出含量ai其所有的质因子。然后求所有质因子的并集(容斥原理),得到与ai不互质的个数,然后架子上的啤酒个数减去ai就是与ai互质的对数。并且我们每次询问可以累积这个对数,这样每次无论是放上还是取下啤酒,都只需找到与进行操作的啤酒的互质的个数即可。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<vector>
      5 using namespace std;
      6 const int maxv = 500010;
      7 const int maxn = 200010;
      8 int v[maxn];
      9 bool isOnShelf[maxn];
     10 vector<int>p[maxv];//存放2~maxv各个数的质因子
     11 int n, q;
     12 int sets[maxv];//存放各个质因子及其乘积的个数
     13 int preCount;//之前架子上的及啤酒个数
     14 long long pre;//之前架子上互质的对数
     15 void Init()
     16 {
     17     for (int i = 2; i < maxv; i++)
     18     {
     19         if (p[i].empty())
     20         {
     21             for (int j = i; j < maxv; j += i)
     22             {
     23                 p[j].push_back(i);
     24             }
     25         }
     26     }
     27 }
     28 
     29 void removeBeer(int x)
     30 {
     31     int len = p[x].size();
     32     int tot = (1 << len) - 1;
     33     int tans = 0;
     34     //二进制枚举质因子个数,进行容斥,找到已有数的集合中与x不互质的个数(也就是含有至少一个相同质因子的个数,p1,p2,...,p_len的并集)
     35     for (int i = 1; i <= tot; i++)
     36     {
     37         //得到当前状态下各质因子的乘积及其个数
     38         int cur = 1,nums=0;
     39         for (int j = 0; j < len; j++)
     40         {
     41             if ((1 << j)&i)
     42             {
     43                 cur *= p[x][j], nums++;
     44             }
     45         }
     46         //在cur的集合中减去一个数(即x自身的若干质因子的乘积),因为要把x从当前数的集合减去
     47         sets[cur]--;
     48         //奇加偶减
     49         if (nums % 2) tans += sets[cur];
     50         else tans -= sets[cur];
     51     }
     52     preCount--;//减去x自身
     53     pre -= (preCount - tans);
     54 }
     55 void addBeer(int x)
     56 {
     57     int len = p[x].size();
     58     int tot = (1 << len) - 1;
     59     int tans = 0;
     60     //二进制枚举质因子个数,进行容斥,找到已有数的集合中与x不互质的个数(也就是含有至少一个相同质因子的个数,p1,p2,...,p_len的并集)
     61     for (int i = 1; i <= tot; i++)
     62     {
     63         //得到当前状态下各质因子的乘积及其个数
     64         int cur = 1, nums = 0;
     65         for (int j = 0; j < len; j++)
     66         {
     67             if ((1 << j)&i)
     68             {
     69                 cur *= p[x][j], nums++;
     70             }
     71         }
     72         //奇加偶减
     73         if (nums % 2) tans += sets[cur];
     74         else tans -= sets[cur];
     75         //在cur的集合中加去一个数(即x自身的若干质因子的乘积),因为要把x放入当前数的集合
     76         sets[cur]++;
     77     }
     78     pre += (preCount - tans);
     79     preCount++;//加上x自身
     80 }
     81 int main()
     82 {
     83     Init();
     84     scanf("%d%d", &n, &q);
     85     for (int i = 1; i <= n; i++) scanf("%d", v + i);
     86     while (q--)
     87     {
     88         int index;
     89         scanf("%d", &index);
     90         if (isOnShelf[index])
     91         {
     92             removeBeer(v[index]);
     93             printf("%I64d
    ", pre);
     94             isOnShelf[index] = false;
     95         }
     96         else
     97         {
     98             addBeer(v[index]);
     99             printf("%I64d
    ", pre);
    100             isOnShelf[index] = true;
    101         }
    102     }
    103     return 0;
    104 }
    View Code
  • 相关阅读:
    vue-cli 打包编译 -webkit-box-orient: vertical 被删除解决办法
    vue静态文件处理
    vue项目关闭eslint检查
    Mac 桌面软件开发基础问答
    Mac App开发
    mac os app 开发
    ffmpeg学习目录收集
    vue中html模板使用绑定的全局函数
    软件版本标识
    shell之ulimit应该注意的事项
  • 原文地址:https://www.cnblogs.com/ivan-count/p/8877195.html
Copyright © 2011-2022 走看看