Codeforces Round #218 (Div. 2) 解题报告
Problem A K-Periodic Array
题意:一个数列中有1与2的序列组成,问最少修改多少个数,能使数列成为从开头开始每k个一组每组的相应位置都一样。
思路:做法就是枚举每一位上的数字1多还是2多,哪个多就让全部的数变成那一个。最后累加求和即可。
代码如下:
1 #include <iostream> 2 #include <fstream> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cmath> 7 #include <algorithm> 8 #include <utility> 9 #include <vector> 10 #include <queue> 11 #include <stack> 12 #define INF 0x7fffffff 13 #define ll long long 14 #define eps 1e-6 15 16 using namespace std; 17 18 int _1[110], _2[110]; 19 20 int main() 21 { 22 // freopen("in.txt", "Cr", stdin); 23 24 int n, k, num[110]; 25 while(scanf("%d%d", &n, &k)!=EOF){ 26 for(int i=0; i<n; i++){ 27 scanf("%d", &num[i]); 28 } 29 memset(_1, 0, sizeof _1); 30 memset(_2, 0, sizeof _2); 31 int ans = 0; 32 for(int j=0; j<n; j++){ 33 if(num[j]==1)_1[j%k]++; 34 if(num[j]==2)_2[j%k]++; 35 } 36 for(int i=0; i<k; i++){ 37 ans+=min(n/k-_1[i], n/k-_2[i]); 38 } 39 printf("%d\n", ans); 40 } 41 return 0; 42 }
Problem B Fox Dividing Cheese
题意:有两个数每次能对他进行一次操作,操作是选取大的一个数对首先(n%2或3或5==0)然后n/=2或3或5,问最后能不能是两个是变成相等的。
思路:很容易想到BFS,有人说数据10e9会不会超时答案是不会的,因为最话情况下是除2。所以复杂度logn不会超时。
代码如下:
1 #include <iostream> 2 #include <fstream> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cmath> 7 #include <algorithm> 8 #include <utility> 9 #include <vector> 10 #include <queue> 11 #include <stack> 12 #define INF 0x7fffffff 13 #define ll long long 14 #define eps 1e-6 15 16 using namespace std; 17 18 struct P{ 19 int a, b, step; 20 }st; 21 22 int BFS() 23 { 24 queue<P> q; 25 q.push(st); 26 while(!q.empty()){ 27 P vex = q.front();q.pop(); 28 P nv; 29 if(vex.a==vex.b) return vex.step; 30 else if(vex.a>vex.b){ 31 if(vex.a%2==0){ 32 nv.a = vex.a; 33 nv.b = vex.b; 34 nv.step = vex.step+1; 35 nv.a/=2; 36 q.push(nv); 37 } 38 if(vex.a%3==0){ 39 nv.a = vex.a; 40 nv.b = vex.b; 41 nv.step = vex.step+1; 42 nv.a/=3; 43 q.push(nv); 44 } 45 if(vex.a%5==0){ 46 nv.a = vex.a; 47 nv.b = vex.b; 48 nv.step = vex.step+1; 49 nv.a/=5; 50 q.push(nv); 51 } 52 } 53 else{ 54 if(vex.b%2==0){ 55 nv.a = vex.a; 56 nv.b = vex.b; 57 nv.step = vex.step+1; 58 nv.b/=2; 59 q.push(nv); 60 } 61 if(vex.b%3==0){ 62 nv.a = vex.a; 63 nv.b = vex.b; 64 nv.step = vex.step+1; 65 nv.b/=3; 66 q.push(nv); 67 } 68 if(vex.b%5==0){ 69 nv.a = vex.a; 70 nv.b = vex.b; 71 nv.step = vex.step+1; 72 nv.b/=5; 73 q.push(nv); 74 } 75 } 76 } 77 return -1; 78 } 79 80 int main() 81 { 82 // freopen("in.txt", "r", stdin); 83 84 while(scanf("%d%d", &st.a, &st.b)!=EOF){ 85 st.step = 0; 86 int ans = BFS(); 87 printf("%d\n", ans); 88 } 89 return 0; 90 }
Problem C Hamburgers
题意:让你做汉堡,汉堡有三种原材料组成告诉你汉堡需要什么样的原材料,然后告诉你现在你每种原材料分别有几个,超市里每种原材料的价格,和你有多少钱。超市里原材料无限。
思路:贪心即可,首先统计每种原材料的需要数量(注意可能为零!)然后由于已有的原材料每种不会超过100所以可以算出做几个汉堡(我直接用枚举的),然后在尽量使用剩下的原材料和钱去做。直到钱用完或者原材料用完。若是原材料用完则再把钱用光。
代码如下:
1 #include <iostream> 2 #include <fstream> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cmath> 7 #include <algorithm> 8 #include <utility> 9 #include <vector> 10 #include <queue> 11 #include <stack> 12 #define INF 0x7fffffff 13 #define ll long long 14 #define eps 1e-6 15 16 using namespace std; 17 18 ll n[4], p[4], mon, num[4]; 19 20 int main() 21 { 22 // freopen("in.txt", "r", stdin); 23 char str[110]; 24 while(scanf("%s", str)!=EOF){ 25 memset(num, 0, sizeof num); 26 for(int i=0; str[i]!=0; i++){ 27 if(str[i]=='B')num[0]++; 28 else if(str[i]=='S')num[1]++; 29 else num[2]++; 30 } 31 for(int i=0; i<3; i++){ 32 scanf("%I64d", &n[i]); 33 } 34 for(int i=0; i<3; i++){ 35 scanf("%I64d", &p[i]); 36 } 37 scanf("%I64d", &mon); 38 for(int i=0; i<3; i++){ 39 if(num[i]==0)n[i]=0; 40 } 41 ll ans = 0; 42 ll nn = INF; 43 while(n[0]>=num[0] && n[1]>=num[1] && n[2]>=num[2]){ 44 n[0]-=num[0];n[1]-=num[1];n[2]-=num[2]; 45 ans++; 46 } 47 if(n[0]+n[1]+n[2]){ 48 while(mon>0){ 49 if(n[0]>=num[0])n[0]-=num[0]; 50 else {mon-=(num[0]-n[0])*p[0];n[0] = 0;} 51 if(n[1]>=num[1])n[1]-=num[1]; 52 else {mon-=(num[1]-n[1])*p[1];n[1] = 0;} 53 if(n[2]>=num[2])n[2]-=num[2]; 54 else {mon-=(num[2]-n[2])*p[2];n[2] = 0;} 55 if(mon<0) break; 56 ans++; 57 if(n[0]+n[1]+n[2]==0)break; 58 } 59 } 60 ll mm = num[0]*p[0]+num[1]*p[1]+num[2]*p[2]; 61 if(mon>=mm)ans+=(mon/mm); 62 printf("%I64d\n", ans); 63 } 64 65 return 0; 66 }
Problem D Vessels
题意:有若干个碗从上到下,在碗中倒水上面的满了会溢出到下面。初始碗是空的给若干个查询1a b代表向a碗倒b单位水,2 a代表查询a碗水量。
思路:我用的是树状数组+二分(后一个可以倒水的碗)树状数组维护每个碗中的水量。复杂度(Ologn*logm*m)
1 #include <iostream> 2 #include <fstream> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <utility> 8 #include <vector> 9 #include <queue> 10 #include <stack> 11 #define INF 0x7fffffff 12 #define ll long long 13 #define eps 1e-6 14 #define LEN 200100 15 16 using namespace std; 17 18 int n; 19 ll ss[LEN], C[3*LEN], num[LEN]; 20 21 ll lowbit(ll x){return x&-x;} 22 23 void init(){ 24 memset(C, 0, sizeof C); 25 memset(ss, 0 ,sizeof ss); 26 } 27 28 ll sum(ll x){ 29 ll ret = 0; 30 while(x>0){ 31 ret+=C[x];x-=lowbit(x); 32 } 33 return ret; 34 } 35 36 void add(int x,int d){ 37 while(x<=n){ 38 C[x]+=d;x+=lowbit(x); 39 } 40 } 41 42 int Bin_S(int l, int r){ 43 if(l==r)return l; 44 if(l>r) return -1; 45 int mid = (l+r)/2; 46 if(sum(mid)-sum(l-1)==ss[mid]-ss[l-1])return Bin_S(mid+1, r); 47 else return Bin_S(l, mid); 48 } 49 50 int main() 51 { 52 // freopen("in.txt", "r", stdin); 53 54 while(scanf("%d", &n)!=EOF){ 55 init(); 56 for(int i=1; i<=n ; i++){ 57 scanf("%I64d", &num[i]); 58 ss[i] = ss[i-1]+num[i]; 59 } 60 int q, op, a, b; 61 scanf("%d", &q); 62 for(int i=0; i<q; i++){ 63 scanf("%d", &op); 64 if(op==1){ 65 scanf("%d%d", &a, &b); 66 while(b){ 67 int pos, loc; 68 pos = Bin_S(a, n); 69 if(pos==-1)break; 70 loc = sum(pos)-sum(pos-1); 71 if(num[pos]-loc<b){ 72 b-=(num[pos]-loc); 73 add(pos, num[pos]-loc); 74 a = pos+1; 75 if(a>n)break; 76 }else{ 77 add(pos, b); 78 b=0; 79 } 80 } 81 }else{ 82 scanf("%d", &a); 83 printf("%I64d\n", sum(a)-sum(a-1)); 84 } 85 } 86 } 87 return 0; 88 }
奔跑吧!少年!趁着你还年轻