ACM-ICPC 2018 南京賽區網路預賽 J. Sum(篩法+分塊)
阿新 • • 發佈:2018-11-17
題目連結:傳送門
題意:給你一個數字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; }