Codeforces_807
A. 严格按照题目给的两个条件来。
#include<bits/stdc++.h> using namespace std; int n,a[1005],b[1005]; int main() { ios::sync_with_stdio(false); cin >> n; for(int i = 1;i <= n;i++) cin >> a[i] >> b[i]; int flag1 = 0,flag2 = 0; for(int i = 1;i <= n;i++) { if(a[i] != b[i]) flag1 = 1; } for(int i = 1;i < n;i++) { if(a[i] < a[i+1]) flag2 = 1; } if(flag1) cout << "rated" <<endl; else if(flag2) cout << "unrated" << endl; else cout << "maybe" << endl; return 0; }
B.可能的值为xx = x+50k(xx >= y),从小到大枚举每一个可能的值,计算cnt就可以了。
#include<bits/stdc++.h> using namespace std; int x,y,p,a[30]; int main() { ios::sync_with_stdio(false); cin >> p >> x >> y; int xx = x; while(x >= y) { int t = x/50%475; for(int i = 1;i <= 25;i++) { t = (t*96+42)%475; a[i] = t+26; if(a[i] == p) { cout << 0 << endl; return 0; } } x -= 50; } x = xx; int cnt = 0,now = 1; while(1) { int t = x/50%475; for(int i = 1;i <= 25;i++) { t = (t*96+42)%475; a[i] = t+26; if(a[i] == p) { cout << cnt << endl; return 0; } } x += 50; now++; if(now == 2) { now = 0; cnt++; } } return 0; }
C.先判断0和-1的情况,然后按大小分类。
若x/y < p/q,我们要把x/y变得尽量大,并且最后的值是p/q,可以变成(np-(y-x))/nq,计算n向上取整,然后结果为nq-y。
若x/y > p/q,我们要把x/y变得尽量小,即只加分母,不加分子,最后变成x/nq == np/nq,计算n向上取整,结果同上。
#include<bits/stdc++.h> using namespace std; long long x,y,xx,yy; int main() { ios::sync_with_stdio(false); int T; cin >> T; while(T--) { cin >> x >> y >> xx >> yy; if(x*yy == y*xx) { cout << 0 << endl; continue; } if(x != 0 && xx == 0 || xx >= yy) { cout << -1 << endl; continue; } if(x*yy < xx*y) { long long t = y-x; long long ans = t/(yy-xx); if(ans*yy-t < ans*xx) ans++; cout << ans*yy-y << endl; } else { long long ans = x/xx; if(ans*xx < x) ans++; cout << ans*yy-y << endl; } } return 0; }
还可以二分n值来写。
D.暴力枚举到100000就可以了。
#include<bits/stdc++.h> using namespace std; int n,a[100005][10],b[100005] = {0},c[100005]; int calc(int x,int y,int z) { int t = 250-x; if(x == -1) return 0; if(2*y > z) return 2*t; if(4*y > z) return 4*t; if(8*y > z) return 6*t; if(16*y > z) return 8*t; if(32*y > z) return 10*t; return 12*t; } bool ok(int x) { int sum1 = 0,sum2 = 0; for(int i = 1;i <= 5;i++) c[i] = b[i]; for(int i = 1;i <= 5;i++) { if(a[2][i] != -1 && a[1][i] > a[2][i]) c[i] += x; } for(int i = 1;i <= 5;i++) { sum1 += calc(a[1][i],c[i],n+x); sum2 += calc(a[2][i],c[i],n+x); } return sum1 > sum2; } int main() { ios::sync_with_stdio(false); cin >> n; for(int i = 1;i <= n;i++) { for(int j = 1;j <= 5;j++) { cin >> a[i][j]; if(a[i][j] >= 0) b[j]++; } } for(int i = 0;i <= 1000000;i++) { if(ok(i)) { cout << i << endl; return 0; } } cout << -1 << endl; return 0; }
E.分别对2的倍数,与2倍数间隔间的数计数,结果个数最多为1的个数,对每个个数,我们判断其是否可行。
我们贪心当前2的倍数之后一个的2的倍数,使剩下来的2的倍数的数量和非2倍数数量和尽可能少,因为剩下的个数为最小的划分的数的个数。
#include<bits/stdc++.h> using namespace std; int n,now = 0,num[65] = {0},two[65] = {0},ans[100005]; bool ok(int x) { int t = two[0]-x; for(int i = 1;i <= now;i++) { if(x >= two[i]) { t -= min(x-two[i],t); x = two[i]; } else t += two[i]-x; t += num[i]; } if(t <= x) return 1; return 0; } int main() { ios::sync_with_stdio(false); cin >> n; long long t = 1; for(int i = 1;i <= n;i++) { long long x; cin >> x; if(x == t) two[now]++; else if(x < t) num[now-1]++; else { while(t < x) { t *= 2; now++; } if(x == t) two[now]++; else num[now-1]++; } } int cnt = 0; for(int i = 1;i <= two[0];i++) { if(ok(i)) ans[++cnt] = i; } if(cnt == 0) cout << -1 << endl; else { for(int i = 1;i <= cnt;i++) cout << ans[i] << " "; cout << endl; } return 0; }
F.首先一种特殊情况,我们选择权值最小(w0)的一条边,设其两点为A,B,不难理解,A,B两点的总p值均为(n-1)*w0。
然后,对于其他的点,取点a,每个点连接着(n-1)条边,对于每条边,权值为w1,设它连的点为a,b,那么,我们可以把除a,b外的所有点先连成最小,即所有边最终跑向A或B,即(n-3)*w0,然后连接A到b或者B到b,再b到a,这里最后两条路径的权值分为两种情况:①若前一点->b 大于 b->a,则总p值为(n-3)*w0+2*w1
②若前一点->b 小于 b->a,则总p值为(n-3)*w0+w前一点->b+w1
这样的情况下,我们在(n-1)*2种情况里取的最小p值为最优解。
第一种情况比较好求解,第二种情况我们可以从到b点的最优转换而来,把原来的a去掉,在最后加上b->a,即-minn+w1。
这样我们就对求解顺序有一定的要求,按边权值从小到大排序,每次更新边的两个点,是符合要求的。
#include<bits/stdc++.h> using namespace std; int n; long long ans[2005]; struct xx { int u,v,w; xx(int a,int b,int c):u(a),v(b),w(c){}; friend bool operator <(xx a,xx b) { return a.w < b.w; } }; vector<xx> v; int main() { ios::sync_with_stdio(false); cin >> n; for(int i = 1;i <= n;i++) ans[i] = 1e18; for(int i = 1;i <= n;i++) { for(int j = i+1;j <= n;j++) { int x; cin >> x; v.push_back(xx(i,j,x)); } } sort(v.begin(),v.end()); long long minn = v[0].w; for(int i = 0;i < v.size();i++) { int x = v[i].u,y = v[i].v,w = v[i].w; long long t = (long long)w*2+minn*(n-3); ans[x] = min(ans[x],min(ans[y]-minn+w,t)); ans[y] = min(ans[y],min(ans[x]-minn+w,t)); } for(int i = 1;i <= n;i++) cout << ans[i] << endl; return 0; }