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\n");
10     else printf("%d\n", 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\n", 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\n", cnt);
40             break;
41         }
42         if (sc.size() == 0)
43         {
44             printf("%d 1\n", cnt);
45             break;
46         }
47     }
48     if(cnt>=maxr)printf("-1\n");
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\n", 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\n");
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("\n");
155         }
156     }
157     else printf("NO\n");
158     return 0;
159 }
View Code

 

转载于:https://www.cnblogs.com/ivan-count/p/8798101.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值