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

    A. Soldier and Bananas

      题意:有个士兵要买w个香蕉,香蕉起步价为k元/个,每多买一个则贵k元。问初始拥有n元的士兵需要借多少钱?

      思路:简单题

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int main()
     5 {
     6     int k, n, w;
     7     scanf("%d%d%d", &k, &n, &w);
     8     int tot = k * (1 + w)*w / 2;
     9     if (tot <= n) printf("0
    ");
    10     else printf("%d
    ", tot - n);
    11 
    12     return 0;
    13 }
    View Code

     B. Soldier and Badges

      题意:有n个徽章,每一个为1~n级其中一级。升一级徽章需要1元。现在要把这n个徽章分发给n个人,要保证两两之间徽章等级不同。求最少要花费多少钱?

      思路:记录每一级的徽章个数。从1开始,如果某一级徽章数目大于1,则对多的徽章升一级,累加到下一级徽章数目中。

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 const int maxn = 3010;
     5 int cnt[maxn * 2];
     6 int main()
     7 {
     8     int n;
     9     scanf("%d", &n);
    10     for (int i = 0; i < n; i++)
    11     {
    12         int v;
    13         scanf("%d", &v);
    14         cnt[v]++;
    15     }
    16     int tot = 0;
    17     for (int i = 1; i <n; i++)
    18     {
    19         if (cnt[i] > 1) tot += cnt[i] - 1, cnt[i + 1] += cnt[i] - 1;
    20     }
    21     if (cnt[n] > 1) tot += (1 + cnt[n] - 1)*(cnt[n] - 1) / 2;
    22     printf("%d
    ", tot);
    23     return 0;
    24 }
    View Code

    C. Soldier and Cards

      题意:有两个人打牌,规则如下:共有n张牌,每个人最初有k1、k2张。每一轮,分别把自己牌堆顶部的一张牌展示,大的人可以拿走两张牌,先把对手的牌放在自己牌堆的底部,再把自己的牌放到底部。问多少轮后谁会赢?或者一直进行下去。

      思路:最多有10张牌,那么一共有10!种排列,对每个排列,一共有11种分法分成两堆,故一共有11!=39916800种方式。模拟打牌过程,当轮数大于(n+1)!时则说明游戏会一直进行下去。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<queue>
     4 using namespace std;
     5 const int maxr = 40000000;//39916800为11!。假如有10张牌,排列共有10!,分给两个人,对每一种排列有11种分法,则总共有11!种
     6 
     7 int main()
     8 {
     9     int n;
    10     scanf("%d", &n);
    11     int k1, k2;
    12     queue<int>fr, sc;
    13     scanf("%d", &k1);
    14     for (int i = 0; i < k1; i++)
    15     {
    16         int num;
    17         scanf("%d", &num);
    18         fr.push(num);
    19     }
    20     scanf("%d", &k2);
    21     for (int i = 0; i < k2; i++)
    22     {
    23         int num;
    24         scanf("%d", &num);
    25         sc.push(num);
    26     }
    27     int cnt = 0;
    28     while (cnt < maxr)
    29     {
    30         cnt++;
    31         int u = fr.front();
    32         fr.pop();
    33         int v = sc.front();
    34         sc.pop();
    35         if (u > v) fr.push(v), fr.push(u);
    36         else if (v > u) sc.push(u), sc.push(v);
    37         if (fr.size() == 0)
    38         {
    39             printf("%d 2
    ", cnt);
    40             break;
    41         }
    42         if (sc.size() == 0)
    43         {
    44             printf("%d 1
    ", cnt);
    45             break;
    46         }
    47     }
    48     if(cnt>=maxr)printf("-1
    ");
    49     return 0;
    50 }
    View Code

    D. Soldier and Number Game

      题意:第一个人给出n=a!/b!,第二个人每次选一个能被n整除的数,并将商代替n,直到值为1.问最多能进行几轮?

      思路:要使除法次数最多,则每次应当选择一个质因子。我们需要找到b+1~a的各个数的所有质因子个数。可以用埃氏筛来求出每个数的质因子。

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 const int maxv = 5000100;
     5 int cnt[maxv];
     6 int sumv[maxv];
     7 void Init()
     8 {
     9     for (int i = 2; i <= 5000000; i++)
    10     {
    11         if (!cnt[i])
    12         {
    13             for (int j = i; j <= 5000000; j += i)
    14             {
    15                 int tmp = j;
    16                 while (tmp%i == 0) cnt[j]++, tmp /= i;
    17             }
    18         }
    19     }
    20 }
    21 int main()
    22 {
    23     Init();
    24     for (int i = 2; i <= 5000000; i++) sumv[i] = sumv[i - 1] + cnt[i];
    25     int n;
    26     scanf("%d", &n);
    27     while (n--)
    28     {
    29         int a, b;
    30         scanf("%d%d", &a, &b);
    31         printf("%d
    ", sumv[a] - sumv[b]);
    32     }
    33     return 0;
    34 }
    View Code

     E. Soldier and Traveling

      题意:给出n个城市,m条无向边。每个城市初始有ai个士兵,现在每个城市的士兵可以待在原来的城市或走到相邻的城市。问最后是否能使得各个城市的士兵数目为bi。

      思路:最大流。起点到各个点i建容量为ai的有向边;各个点i+n到终点建容量为bi的有向边;如果存在道路(u,v),则从u->v+n,v->u+n建边,容量为INF;并且可以待在原地,则i->i+n建边,容量为INF。跑最大流即可。此处采用Dicnic模板。

      1 #include<iostream>
      2 #include<queue>
      3 #include<cstring>
      4 #include<cstdio>
      5 using namespace std;
      6 const int INF = 0x3f3f3f3f3f;
      7 const int maxn = 310;
      8 const int maxm = 21000;
      9 
     10 struct edge
     11 {
     12     int to, next, cap, flow;
     13     edge(int tt=0,int cc=0,int ll=0,int nn=0):to(tt),cap(cc),flow(ll),next(nn){}
     14 };
     15 edge Edge[maxm];
     16 int Head[maxn], tmpHead[maxn], totedge;
     17 
     18 
     19 
     20 struct Dicnic 
     21 {
     22     int nodes, st, ed, totedge;
     23     int level[maxn];
     24     bool vis[maxn];
     25     int needflow;
     26 
     27     void Init(int node, int src, int dst)
     28     {
     29         nodes = node, st = src, ed = dst;
     30         memset(Head, -1, sizeof(Head));
     31         totedge = 0;
     32     }
     33     void addedge(int u, int v, int c)
     34     {
     35         Edge[totedge] = edge(v, c, 0, Head[u]);
     36         Head[u] = totedge++;
     37         Edge[totedge] = edge(u, 0, 0, Head[v]);
     38         Head[v] = totedge++;
     39     }
     40     bool Dicnic_bfs()//生成层次图
     41     {
     42         queue<int>q;
     43         int i, u, v;
     44         memset(level, -1, sizeof(level));
     45         memset(vis, 0, sizeof(vis));
     46 
     47         q.push(st);
     48         level[st] = 0;
     49         vis[st] = true;
     50 
     51         while (!q.empty())
     52         {
     53             u = q.front();
     54             q.pop();
     55             if (u == ed) return true;
     56             for (int i = Head[u]; i != -1; i = Edge[i].next)
     57             {
     58                 v = Edge[i].to;
     59                 if (Edge[i].cap > Edge[i].flow && !vis[v] && level[v] == -1)
     60                 {//保证这条边有剩余容量,属于残量网络
     61                     vis[v] = true;
     62                     level[v] = level[u] + 1;
     63                     q.push(v);
     64                 }
     65             }
     66         }
     67         return false;
     68     }
     69 
     70     int Dicnic_dfs(int u, int maxf)
     71     {
     72         if (u == ed || maxf == 0) return maxf;
     73 
     74         int flow = 0, f;
     75         for (int &i = tmpHead[u]; i != -1; i = Edge[i].next)
     76         {
     77             int v = Edge[i].to;
     78             if (Edge[i].cap - Edge[i].flow > 0 && level[v] == level[u] + 1)
     79             {
     80                 f = Dicnic_dfs(v, min(maxf, Edge[i].cap - Edge[i].flow));
     81                 if (f > 0)
     82                 {
     83                     Edge[i].flow += f;
     84                     Edge[i ^ 1].flow -= f;
     85                     flow += f;
     86                     maxf -= f;
     87                     if (maxf == 0) break;
     88                     if (flow >= needflow) return flow;
     89                 }
     90             }
     91         }
     92         return flow;
     93     }
     94 
     95     int Dicnic_maxflow(int needf = INF)
     96     {
     97         int ret = 0;
     98         needflow = needf;
     99         while (Dicnic_bfs())
    100         {
    101             memcpy(tmpHead, Head, sizeof(Head));
    102             ret += Dicnic_dfs(st, INF);
    103             if (ret >= needflow) return ret;
    104         }
    105         return ret;
    106     }
    107 };
    108 
    109 
    110 int a[110], b[110];
    111 int mp[110][110];
    112 int main()
    113 {
    114     int n, m;
    115     scanf("%d%d", &n, &m);
    116     Dicnic dicnic;
    117     int ta = 0, tb = 0;
    118     for (int i = 1; i <= n; i++) scanf("%d", a + i),ta+=a[i];
    119     for (int i = 1; i <= n; i++) scanf("%d", b + i),tb+=b[i];
    120     int src = 0, dst = n * 2 + 1;
    121     dicnic.Init(n * 2 + 2, src, dst);
    122     for (int i = 1; i <= n; i++) dicnic.addedge(src, i, a[i]);
    123     for (int i = n + 1; i <= n * 2; i++) dicnic.addedge(i, dst, b[i-n]);
    124     for (int i = 1; i <= n; i++) dicnic.addedge(i, i + n, INF);
    125     for (int i = 0; i < m; i++)
    126     {
    127         int u, v;
    128         scanf("%d%d", &u, &v);
    129         dicnic.addedge(u, v + n, INF);
    130         dicnic.addedge(v, u + n, INF);
    131     }
    132     int maxflow = dicnic.Dicnic_maxflow();
    133     if (maxflow == ta && ta == tb)
    134     {
    135         printf("YES
    ");
    136         for (int i = 1; i <= n; i++)
    137         {
    138             for (int j = Head[i]; j != -1; j = Edge[j].next)
    139             {
    140                 if (Edge[j].cap)
    141                 {
    142                     int v = Edge[j].to;
    143                     mp[i][v-n] =Edge[j].flow;
    144                 }
    145             }
    146         }
    147         for (int i = 1; i <= n; i++)
    148         {
    149             for (int j = 1; j <= n; j++)
    150             {
    151                 if (j == 1) printf("%d", mp[i][j]);
    152                 else printf(" %d", mp[i][j]);
    153             }
    154             printf("
    ");
    155         }
    156     }
    157     else printf("NO
    ");
    158     return 0;
    159 }
    View Code
  • 相关阅读:
    雷文-武汉科技大学-软件工程-本科-20111020(2011年校园招聘找工作时的简历)
    雷文-武汉科技大学-软件工程-本科-20111020(2011年校园招聘找工作时的简历)
    大学生应当趁早谋划未来
    大学生应当趁早谋划未来
    提前了解客户背景很有必要
    提前了解客户背景很有必要
    雷文-武汉科技大学-软件工程-本科-20131118(我的最新简历)
    雷文-武汉科技大学-软件工程-本科-20131118(我的最新简历)
    《商君列传第八》–读书总结
    《商君列传第八》–读书总结
  • 原文地址:https://www.cnblogs.com/ivan-count/p/8798101.html
Copyright © 2011-2022 走看看