题目链接:传送门
题意:给你一个数字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;
}