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

浙公网安备 33010602011771号