2020中国大学生程序设计竞赛(CCPC)网络选拔赛min25筛

2020中国大学生程序设计竞赛(CCPC) - 网络选拔赛(部分题解)

这次B题ac太多人了,现场时过了快700多人。导致我们队写完签到拼命打表这个题。思路不难,求一次[3,n+1]的连续和,再求[3,n]的素数和。但问题是n太大了,线性筛必定tle,而我们队没有数论选手就很难受(哭)。最后只能打表还是tle。赛后还有各种实验,就先补上部分题解。
B题XOR

B题真就人均min_25筛,是我太菜了。思路并不难,从{2}开始,3如果连到2边,权值只能是2*3=6,4的话可以连到{2,3}中的2,权值即为本身,确实和Kruskal有那么一丢丢关系,每次把j加入到已经连好的最小生成树{2,3,···,j-1}中去,所以对于质数来说,只能连2,对于合数j来说,[2,j-1]必有其因子d。于是可以认为求3-n+1的和,在加上期间的素数和。
但是min_25实在是看不懂,网上找了这位大佬的min25板子过的,min25之后再补,太菜了只能看懂简单数论。可以参考min_25学习笔记
ac代码:

#include <iostream>
#include<math.h>
#define ll long long
using namespace std;
const int N = 1000010;
int prime[N], id1[N], id2[N], flag[N], ncnt, m;
ll g[N], sum[N], a[N], T;
ll n;
int ID(ll x) {
    
    
	return x <= T ? id1[x] : id2[n / x];
}
ll calc(ll x) {
    
    
	return x * (x + 1) / 2 - 1;
}
ll f(ll x) {
    
    
	return x;
}
void init(ll n) {
    
    
	T = sqrt(n + 0.5);
	for (int i = 2; i <= T; i++) {
    
    
		if (!flag[i]) prime[++ncnt] = i, sum[ncnt] = sum[ncnt - 1] + i;
		for (int j = 1; j <= ncnt && i * prime[j] <= T; j++) {
    
    
			flag[i * prime[j]] = 1;
			if (i % prime[j] == 0) break;
		}
	}
	for (ll l = 1; l <= n; l = n / (n / l) + 1) {
    
    
		a[++m] = n / l;
		if (a[m] <= T) id1[a[m]] = m; else id2[n / a[m]] = m;
		g[m] = calc(a[m]);
	}
	for (int i = 1; i <= ncnt; i++)
		for (int j = 1; j <= m && (ll)prime[i] * prime[i] <= a[j]; j++)
			g[j] = g[j] - (ll)prime[i] * (g[ID(a[j] / prime[i])] - sum[i - 1]);
}
ll solve(ll x) {
    
    
	if (x <= 1) {
    
     return x; }
	return n = x, init(n), g[ID(n)];
}
int main() {
    
    
	int T;
	cin >> T;
	while (T--)
	{
    
    
		/*
		memset(g, 0, sizeof(g));
		memset(a, 0, sizeof(a));
		memset(sum, 0, sizeof(sum));
		memset(prime, 0, sizeof(prime));
		memset(id1, 0, sizeof(id1));
		memset(id2, 0, sizeof(id2));
		memset(flag, 0, sizeof(flag));
		*/
		ncnt = m = 0;
		ll k;
		scanf("%lld%lld", &n,&k);
		ll sum = 0;
		if (n == 1) {
    
    
			printf("0\n"); continue;
		}else if (n == 2) {
    
    
			printf("6\n"); continue;
		}
		n++;
		if (n % 2 == 0)sum += ((((n - 2) / 2) % k)*(n + 3)) % k;
		else sum += ((((n +3) / 2) % k)*(n -2) ) % k;
		sum += (solve(n)-2)%k;
		sum = sum % k;
		printf("%lld\n", sum);
	}
	return 0;
}

C题Express Mail Taking
C题的话,题意是每次取东西都必须先到k号密码柜输密码才能取,那不妨以k号柜作为起始点,这样除了最后一个快递点不用到k号柜,其他必须走两趟k号柜的路,是固定长度,而最后一个走的距离是Xi最小的那个最短。这样折返回去的路线就最短。所以每读取一个数给总路程加上2*abs(k-x),然后用min保存坐标最小的点,减去重复计算的k-x,然后加上min到1的路程(注意这段路是min-1),再加上最开始1到k的路程(注意这段路是k-1
ac代码:

#include<iostream>
#include<stdio.h>
#define ll long long
using namespace std;
int main() {
    
    
	ll t, n;
	ll x[50];
	cin >> t;
	while (t--) {
    
    
		ll n, m, k;
		ll sum=0;
		scanf("%lld%lld%lld", &n,&m,&k);
		ll min = n,y;
		for (int i = 0; i < m; i++) {
    
    
			scanf("%lld", &y);
			if (min > y)min = y;
			if(k>y)sum += 2*(k - y);
			else sum +=2*( y - k);
		}
		sum = sum + k-1 - abs(k - min)+min-1;
		printf("%lld\n", sum);
	}

	return 0;
}

F题Robotic Class
F题nim博弈,实际还是套了层皮的数论。质因数分解题。不过2须特判,因为2只能分成2个1,偶数个分解,实际对结果并无影响。
nim函数值f(k)=k的奇质因数个数+[k为偶数]。
我是数论废物,ac代码待补。
G题CCPC Training Class
G题规律很明显,出现最多次数的字符的个数就是答案。只要把出现最多次数的字符放在最前面就可以构造完成。这里有个坑,比赛时好像数据较弱,赛后提交一直tle,不是cin和cout输入输出问题,而是不能用数组s[10005]存取改字符串,数组访问会tle,需要用一个字符char tmp,来每次读取字符就放放到桶里计数。
ac代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#define ll long long
using namespace std;
int num[26];

int main() {
    
    
    int n;
    char tmp;
    scanf("%d\n",&n);
    int k = 1;
    while (k<=n) {
    
    
        for (int i = 0; i < 26; i++) num[i] = 0;
        while (true) {
    
    
            scanf("%c", &tmp);
            if (tmp > 'z'||tmp< 'a')  break;
            num[tmp - 'a']++;
        }
        int max = -1;
        for (int i = 0; i < 26; i++) {
    
    
            if (num[i] > max)max = num[i];
        }
        printf("Case #%d: %d\n", k,max);
        k++;
    }

    return  0;
}

J题Reports
J题比较水,判断相邻有没有相同即可,有就跳出循环输出NO,无就循环结束输出YES。代码就不贴了。
K题3x3 Convolution
K题发现规律也不难写,可能会卡在这个公式上,实际上这类似矩阵卷积,还好我学了计算机视觉(得意) ,实际上运算无限次要么是原矩阵,要是全0矩阵,只有矩阵K只有[0,0]处有非零值时,是原矩阵,其他情况均输出全0矩阵。证明说实话不会证,没错猜规律才是王道 。贴上题解证明吧:
在这里插入图片描述
代码不给了,也是简单的判断即可。
L题数位dp待补
L题似乎有原题数位dp
其他非数论题待补。

猜你喜欢

转载自blog.csdn.net/qq_43305312/article/details/108789074