ACM-ICPC 2018 南京赛区网络预赛 J. Sum(筛法+分块)

题目链接传送门

题意:给你一个数字n,让你求从1到n的每个数的乘数组合的个数,要求乘数满足不能被平方数整除。

解决方法:比赛的时候想到用线性筛来先将不符合的数先标记出来,然后再去便利统计个数。一开始t了,后来改成分块后因为代码写挫wa了好多次,还是自己太菜了。

下面附上比赛ac代码

#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 21000010;
long long tag[21000010];
long long prime[21000010];
long long sum[21000010];
void Prime() {
	memset(tag, 0, sizeof(tag));
	int cnt = 0;
	tag[0] = tag[1] = 1;
	for (long long i = 2; i <= sqrt((double)maxn); i++) {
		if (tag[i] == 1) continue;
		prime[cnt++] = i*i;
		tag[i*i] = 1;
	}
	for (long long j = 0; j < cnt; j++) {
		for (long long i = 2; i*prime[j] < maxn; i++) {
			tag[i*prime[j]] = 1;
		}
	}
}
int main(void) {
	int t;
	scanf("%d", &t);
	Prime();
	tag[1] = 0;
	sum[0] = 0;
	for (int i = 1; i < maxn-1; i++) {
		sum[i] += sum[i - 1]+tag[i];
	}
	while (t--) {
		long long a, b;
		scanf("%lld", &a);
		if (a <= 0) {
			printf("0\n");
		}
		long long tot= 0;
		for (long long i = 1; i <= a; ) {

			if (tag[i] != 1) {
				int t = a / (a / i);
				tot += (a / i - sum[a / i])*(t-i+1-(sum[t]-sum[i]));
				i = t + 1;
			}
			else i++;
		}
		printf("%lld\n", tot);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liexss/article/details/82432426