zoukankan      html  css  js  c++  java
  • VK Cup 2018

    A. Primal Sport

      题意:有两个人轮流玩游戏。给出数X(i-1),轮到的人需要找到一个小于X(i-1)的素数x,然后得到Xi,Xi是x的倍数中大于等于X(i-1)的最小的数。现在已知X2,求最小的X0?

      思路:根据题意,X1的取值范围为【X1-X2的最大质因子+1,X2),同理可知X0的取值范围为【X1-X1的最大质因子+1,,X1)。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 using namespace std;
     6 const int maxn = 1000010;
     7 int Res[maxn],tmp[maxn];
     8 void Init()
     9 {
    10     memset(tmp, -1, sizeof(tmp));
    11     for (int i = 2; i < maxn; i++)
    12     {
    13         if (tmp[i] == -1)
    14         {
    15             for (int j = 2*i; j < maxn; j += i) tmp[j] = i;//标记质因子
    16         }
    17         if (tmp[i] == -1) Res[i] = i;//为质数
    18         else Res[i] = i - tmp[i] + 1;//不是质数,tmp[i]为最大质因子
    19     }
    20 }
    21 int main()
    22 {
    23     Init();
    24     int n;
    25     scanf("%d", &n);
    26     int L = Res[n];
    27     int ans = n;
    28     for (int i = L; i < n; i++) ans = min(Res[i], ans);
    29     printf("%d
    ", ans);
    30     return 0;
    31 }
    View Code

    B. Producing Snow

      题意:有n天,每天都会产生Vi体积的雪花堆(堆与堆之间独立),每天存在的雪花都会融化Ti,问n天中各天融化的体积和。

      思路:用优先队列或最小堆维护,将Vi+sum(T1-Ti-1)加入队列或堆。堆中所有小于等于sum(T1-Ti)的都需要pop,当天融化的体积为所有pop出来的减去sum(Ti-Ti-1)加上还在堆里的数目*Ti.

    堆实现:

     1 #include<iostream>
     2 #include<vector>
     3 #include<algorithm>
     4 #include<functional>
     5 using namespace std;
     6 const int maxn = 100010;
     7 int V[maxn],T[maxn];
     8 vector<long long>Heap;
     9 int main()
    10 {
    11     int n;
    12     scanf("%d", &n);
    13     make_heap(Heap.begin(), Heap.end(), greater<long long>());//建立最小堆
    14     for (int i = 1; i <= n; i++) scanf("%d", V + i);
    15     for (int i = 1; i <= n; i++) scanf("%d", T + i);
    16     long long pre = 0;
    17     for (int i = 1; i <= n; i++)
    18     {
    19         Heap.push_back(V[i]+pre);
    20         push_heap(Heap.begin(), Heap.end(), greater<long long>());
    21         long long tot = 0;
    22         while (Heap.size()&&Heap[0] <= T[i]+pre)
    23         {
    24             tot += Heap[0]-pre;
    25             pop_heap(Heap.begin(), Heap.end(), greater<long long>());
    26             Heap.pop_back();
    27         }
    28         if (Heap.size())
    29         {
    30             tot += 1ll*T[i]*Heap.size();
    31         }
    32         if (i == n) printf("%I64d
    ", tot);
    33         else printf("%I64d ", tot);
    34         pre += T[i];
    35     }
    36     return 0;
    37 }
    View Code

    优先队列实现:

     1 #include<queue>
     2 #include<functional>
     3 #include<iostream>
     4 #include<cstdio>
     5 using namespace std;
     6 const int maxn = 100010;
     7 int V[maxn], T[maxn];
     8 
     9 int main()
    10 {
    11     priority_queue<long long, vector<long long>, greater<long long> >pq;
    12     int n;
    13     scanf("%d", &n);
    14     for (int i = 1; i <= n; i++)
    15     {
    16         scanf("%d", V + i);
    17     }
    18     for (int i = 1; i <= n; i++)
    19     {
    20         scanf("%d", T + i);
    21     }
    22     long long pre = 0;
    23     for (int i = 1; i <= n; i++)
    24     {
    25         pq.push(V[i] + pre);
    26         long long tot = 0;
    27         while (pq.size() && pq.top() <= pre + T[i])
    28         {
    29             tot += pq.top() - pre;
    30             pq.pop();
    31         }
    32         tot += pq.size()*T[i];
    33         pre += T[i];
    34         if (i == n) printf("%I64d
    ", tot);
    35         else printf("%I64d ",tot);
    36     }
    37     return 0;
    38 }
    View Code

     C. Perfect Security

      题意:有n个数字构成的序列A,有一串n个数的key——P,求出key的某一个重新排序的序列,使得Ai^Pi最后得到的结果串字典序最小,并输出该结果串。

      思路:01异或字典树。注意插入的细节;查询时记得数目标记减1,因为P中每个数只能用一次。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cstdio>
     5 using namespace std;
     6 const int maxn = 300010;
     7 int A[maxn],P[maxn];
     8 const int bits = 32;
     9 const int SIZE = 2;
    10 struct Trie
    11 {
    12     int Nums[maxn*bits][SIZE];
    13     int ex[maxn*bits*SIZE];//经过结点i的数的数目
    14     int Tot;
    15 
    16     void clear()
    17     {
    18         memset(Nums[0], 0, sizeof(Nums[0]));
    19         Tot = 1;
    20     }
    21 
    22     void insert(int Num)
    23     {
    24         int Now = 0, curchr;
    25         for (int i = 29; i >=0; i--)
    26         {
    27             int c = ((Num>>i)&1);
    28             if (!Nums[Now][c])
    29             {
    30                 memset(Nums[Tot], 0, sizeof(Nums[Tot]));
    31                 ex[Tot] = 0;
    32                 Nums[Now][c] = Tot++;
    33             }
    34             ex[Nums[Now][c]]++;//表示经过该点的数的数目
    35             Now = Nums[Now][c];
    36         }
    37     }
    38     int Search(int Num)
    39     {
    40         int u = 0,c;
    41         for (int i = 29; i >=0; i--)
    42         {
    43             c =((Num>>i)&1);
    44             if (ex[Nums[u][c]])
    45             {
    46                 u = Nums[u][c];
    47                 ex[u]--;
    48                 Num ^= (c << i);
    49             }
    50             else
    51             {
    52                 u = Nums[u][c^1];
    53                 ex[u]--;
    54                 Num ^= ((c ^ 1) << i);
    55             }
    56         }
    57         return Num;
    58     }
    59 
    60 }tree;
    61 int main()
    62 {
    63     tree.clear();
    64     int n;
    65     scanf("%d", &n);
    66     for (int i = 1; i <= n; i++)
    67     {
    68         scanf("%d", A + i);
    69     }
    70     for (int i = 1; i <= n; i++)
    71     {
    72         scanf("%d", P+i);
    73     }
    74     for (int i = 1; i <= n; i++) tree.insert(P[i]);
    75     for (int i = 1; i <= n; i++)
    76     {
    77         int ans = tree.Search(A[i]);
    78         if (i == n) printf("%d
    ", ans);
    79         else printf("%d ", ans);
    80     }
    81     return 0;
    82 }
    View Code

     D. Picking Strings

      题意:给出S原串和T原串,每次各选取一个子区间,问在题目的变换下:A->BC,B->AC,C->AB,AAA->empty,是否能够从S串变换到T串?

      思路:

    B->AC->AAB->AAAC->C;C->AB->AAC->AAAB->B(B和C等价,可以将所有C替换为B)
    AB->AAC->AAAB->B;B->AC->AB(B前面的A可以任意增减)
    A->BC->BB(A可以转换为BB)
    B->AB->BBB(已有B时,B的数量增加任意偶数个)
    故只需考虑子串末尾A。由于末尾A无法被转化成,故原串和目标串末尾A数目需要保留相同个数
    1.当T串B少,无解(B无法消除,只能增加)
    2.当两串B数目奇偶数不同,无解(B只能增加偶数个)
    3.T串末尾A比S串多,无解(末尾A无法增加,只能减少)
    否则(两串B数目奇偶相同):
    4.T串B多,S串末尾A多,必有解
    5.两串B相同,S串末尾A比T串多的数目为3的倍数时有有解
    6.两串A相同,S串有B即可。
    7.其他无解

     1 //B->AC->AAB->AAAC->C;C->AB->AAC->AAAB->B(B和C等价,可以将所有C替换为B)
     2 //AB->AAC->AAAB->B;B->AC->AB(B前面的A可以任意增减)
     3 //A->BC->BB(A可以转换为BB)
     4 //B->AB->BBB(已有B时,B的数量增加任意偶数个)
     5 //故只需考虑子串末尾A。由于末尾A无法被转化成,故原串和目标串末尾A数目需要保留相同个数
     6 //1.当T串B少,无解(B无法消除,只能增加)
     7 //2.当两串B数目奇偶数不同,无解(B只能增加偶数个)
     8 //3.T串末尾A比S串多,无解(末尾A无法增加,只能减少)
     9 //否则(两串B数目奇偶相同):
    10 //4.T串B多,S串末尾A多,必有解
    11 //5.两串B相同,S串末尾A比T串多的数目为3的倍数时有有解
    12 //6.两串A相同,S串有B即可。
    13 //7.其他无解
    14 #include<iostream>
    15 #include<algorithm>
    16 #include<cstring>
    17 #include<cstdio>
    18 using namespace std;
    19 const int maxn = 100010;
    20 char S[maxn], T[maxn];
    21 //记录前i个字符中B+C的前缀和;记录以i结尾的连续A的个数
    22 int Sa[maxn], Sb[maxn];
    23 int Ta[maxn], Tb[maxn];
    24 int main()
    25 {
    26     int n;
    27     scanf("%s%s%d", S+1, T+1,&n);
    28     int len1 = strlen(S+1), len2 = strlen(T+1);
    29     for (int i = 1; i <= len1; i++)
    30     {
    31         if (S[i] == 'A') Sa[i] = Sa[i - 1] + 1;
    32         Sb[i] = (S[i] == 'A') ? Sb[i - 1] : Sb[i - 1] + 1;
    33     }
    34     for (int i = 1; i <= len2; i++)
    35     {
    36         if (T[i] == 'A') Ta[i] = Ta[i - 1] + 1;
    37         Tb[i] = (T[i] == 'A') ? Tb[i - 1] : Tb[i - 1] + 1;
    38     }
    39     while (n--)
    40     {
    41         int a, b, c, d;
    42         scanf("%d%d%d%d", &a, &b, &c, &d);
    43         int len1 = b - a + 1, len2 = d - c + 1;
    44         int t_sa = min(len1, Sa[b]), t_sb = Sb[b] - Sb[a - 1];
    45         int t_ta = min(len2, Ta[d]), t_tb = Tb[d] - Tb[c - 1];
    46         //当T串B少,当两串B数目奇偶数不同,T串末尾A比S串多,无解
    47         if (t_sb > t_tb || (t_sb % 2) != (t_tb % 2) || t_ta > t_sa) printf("0");
    48         else if(t_tb>t_sb&&t_sa>t_ta)//隐含两串B数目奇偶相同
    49         {//T串B多,S串A多(多出的A可以转化为BB,前面非连续的A始终可以转化)
    50             printf("1");
    51         }
    52         else if (t_tb == t_sb)
    53         {//此时只有Sa-Ta多出的a的数目为3的倍数才能转化
    54             if ((t_sa - t_ta) % 3 == 0) printf("1");
    55             else printf("0");
    56         }
    57         else if (t_ta == t_sa)
    58         {//此时只要sb的数目大于0
    59             if (t_sb) printf("1");
    60             else printf("0");
    61         }
    62         else printf("0");
    63     }
    64     printf("
    ");
    65     return 0;
    66 }
    View Code

     A2. Protect Sheep

      题意:有一个牧场,‘S’为羊,现在需要放置‘D’狗,防止羊‘S’被狼‘W’通过上下左右吃到。任意一种方案即可,放置狗的数目不限

      思路:简单DFS

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 const int maxn = 510;
     6 char MP[maxn][maxn];
     7 bool Find[maxn][maxn];
     8 int dx[] = { 0,0,1,-1 };
     9 int dy[] = { 1,-1,0,0 };
    10 int R, C;
    11 bool flag;
    12 void DFS(int ux,int uy)
    13 {
    14     for (int i = 0; i < 4; i++)
    15     {
    16         if (!flag) return;
    17         int tx = ux + dx[i], ty = uy + dy[i];
    18         if (tx >= R || tx < 0 || ty >= C || ty < 0) continue;
    19         if (MP[tx][ty] == 'W')
    20         {
    21             flag = false;
    22             return;
    23         }
    24         else if (MP[tx][ty] == 'S'&&!Find[tx][ty])
    25         {
    26             Find[tx][ty] = true;
    27             DFS(tx, ty);
    28         }
    29         else if (MP[tx][ty] == '.') MP[tx][ty] = 'D';
    30     }
    31 }
    32 int main()
    33 {
    34     scanf("%d%d", &R, &C);
    35     flag = true;
    36     for (int i = 0; i < R; i++) scanf("%s", MP + i);
    37     for (int i = 0; i < R; i++)
    38     {
    39         for (int j = 0; j < C; j++)
    40         {
    41             if (MP[i][j] == 'S' && !Find[i][j])
    42             {
    43                 Find[i][j] = true;
    44                 DFS(i, j);
    45             }
    46         }
    47     }
    48     if (flag)
    49     {
    50         printf("Yes
    ");
    51         for (int i = 0; i < R; i++) printf("%s
    ", MP + i);
    52     }
    53     else printf("No
    ");
    54     return 0;
    55 }
    View Code
  • 相关阅读:
    python count函数
    kubenetes服务发现
    k8s网络
    k8s创建pod流程
    openstack创建虚拟流程、各组件介绍
    生产者消费者问题
    Date类和Calendar类
    Timer定时器
    Java中的克隆
    注解
  • 原文地址:https://www.cnblogs.com/ivan-count/p/8556472.html
Copyright © 2011-2022 走看看