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 }
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 }
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 }
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 }
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 }