【CF】Good Bye 2018
Happy New Year!
CF GoodBye2018 官方题解
只做出来前4道,被E题搞自闭之后就睡了orz.
A题:水题,不想说题意orz
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int a,b,c; int main() { cin>>a>>b>>c; a = min(a,min(b-1,c-2)); b = min(b,min(a+1,c-1)); c = min(c,min(a+2,b+1)); a = max(a,0); b = max(b,0); c = max(c,0); cout<<a+b+c<<endl; }B题 给你n个A类型点和n个B类点,两两匹配,保证可以找到一个点满足对于所有匹配有(ax+bx,ay+by)。 根据数据观察发现直接所有的横坐标加起来/n,所有纵坐标加起来/n就可以了。(人生第一次被hack orz orz orz 没开long long orz orz orz )
#include<iostream> #include<cstdio> #define int long long using namespace std; int n; int X,Y; main() { cin>>n; for(int i=1;i<=2*n;i++) { int x,y; cin>>x>>y; X+=x; Y+=y; } X/=n; Y/=n; cout<<X<<' '<<Y<<endl; }C题 编号1-n, 球开始在1手上,顺时针(编号变大)选择扔一个距离k(小于n)(之后固定不变),又一直转,直到又到1手上.这样一次的权值为转一圈所有人的编号总和.求出所有的可能编号总和,n1e9. 随便找几个数看一下规律,我们发现,和n的因子有关系,枚举一下因子就出来了.
#include<stdio.h> #include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #define int long long using namespace std; const int maxn = 1e5 + 5; int n; int st[maxn],tot; main() { cin>>n; int sq = sqrt(n); for(int i=1;i<=sq;i++) { if(n%i==0) { int xs = n/i; int o = i; st[++tot] = 1ll*(2+(xs-1)*o)*xs/2; if(i*i!=n) { o = n/i; xs = i; st[++tot] = 1ll*(2+(xs-1)*o)*xs/2; } } } sort(st+1,st+1+tot); tot = unique(st+1,st+1+tot)-st-1; for(int i=1;i<=tot;i++) cout<<st[i]<<' '; }D题 考试的时候找规律出来的,,发现减去n!之后有规律.官方题解..也没怎么看懂,以后再搞懂吧orzorzorz
#include<stdio.h> #include<iostream> using namespace std; const int mod = 998244353; int add(int x,int y) { x+=y; return x>=mod?x-mod:x; } int sub(int x,int y) { x-=y; return x>=mod?x+mod:x; } int mul(int x,int y) { return 1ll*x*y%mod; } int jc,now; int main() { now = 1; jc = 1; int n; cin>>n; if(n==1) { puts("1"); return 0; } for(int i=2;i<=n;i++) { jc = mul(jc,i); now = add( mul(sub(now,1),i) , jc); } cout<<now; }E 题,给出n个点的度数,你给出第n+1个点的度数的所有可能性使得这张图为简单无向图。 由于握手引理,对于无向图的度数为奇数的点个数为偶个,那么我们可以得到最后答案的奇偶。然后就按大到小排序,然后从大的开始,减去大的所有度数往后面的点全部删一个度数,如果不够删看n+1点能不能补完,以及至少可以补多少和最多连多少。 之后得到上下界之后依次+2就可以了,实现利用二分。
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #define int long long using namespace std; const int maxn = 5e5+5; int n;int top; int a[maxn],sm[maxn]; main() { int orz = 0; scanf("%I64d",&n); for(int i=1;i<=n;i++) { int x; scanf("%I64d",&x); if(x) a[++top] = x; orz = (orz+x)&1; } n = top; sort(a+1,a+1+n,greater<int>()); for(int i=1;i<=n;i++) sm[i] = sm[i-1] + a[i]; int L = 0; int R = n; for(int i=1;i<=n;i++) { int j = lower_bound(a+i+1,a+1+n,i,greater<int>())-a; int a = sm[i]; int b = (j-i-1)*i + sm[n] - sm[j-1] + i*(i-1); if(a>b) { if(a-b-i>0) { puts("-1"); exit(0); } else L = max(L,a-b); } R = min(R,j-(a-b-i)); // cout<<j<<endl; } if(orz) { if(!(L&1)) L++; if(!(R&1)) R--; } else { if(L&1) L++; if(R&1) R--; } bool fl = 0; for(int i=L;i<=R;i+=2) printf("%I64d ",i),fl = 1; if(!fl) puts("-1"); }F题,在一条路上有陆地、水域和岩浆三种地形,用走5s/m(只能在陆上走),用游3s/m(只能在水上飞),用飞1s/m,飞1s需要1能量,每走一m或者游一m得到1能量,求花费最少时间走到终点。 考虑贪心就好(然而E题卡自闭后考场上思维僵化+想睡觉orz),如果遇到岩浆,肯定要飞过去,如果不能飞过去只能回走0.5m然后又走0.5m攒能量,那么优先攒能量地在水上。而对于最后可能剩下能量的情况肯定是浪费,那么除了岩浆以外,优先选择在陆地的地方飞行,那么考虑陆地花费的能量既不能超过攒的能量的1/2(因为飞花了1能量也少得了一能量),也不能超过陆地走的长度。
#include<cstdio> #include<algorithm> #include<iostream> #define int long long using namespace std; const int maxn = 2e5+5; int n; int nl,tgra; int a[maxn]; char ss[maxn]; int tim; main() { cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; scanf("%s",&ss[1]); bool flag = 0; for(int i=1;i<=n;i++) { if(ss[i]=='L') { tim += a[i]; nl -= a[i]; if(nl<0) { tim += (-nl)*(flag?3:5); nl = 0; } } else if(ss[i]=='W') { flag = 1; nl += a[i]; tim += 3*a[i]; } else { nl += a[i]; tgra += 2*a[i]; tim += 5*a[i]; } tgra = min(tgra,nl); } if(nl>0) { tim -= (5-1)*tgra/2; tim -= (3-1)*(nl - tgra)/2; } cout<<tim; }