题目链接:ACM-ICPC 2018 南京赛区网络预赛 J-Sum
\;\;\;\; f [ i ] f[i] f[i] 表示有序整数对 ( a , b ) (a,b) (a,b),满足 a b = i ab=i ab=i 的数量。
\;\;\;\;\;\; eg: f [ 6 ] = 4 f[6] = 4 f[6]=4, 6 = 1 ⋅ 6 = 6 ⋅ 1 = 2 ⋅ 3 = 3 ⋅ 2 6 = 1 \cdot 6 = 6 \cdot 1 = 2 \cdot 3 = 3 \cdot 2 6=1⋅6=6⋅1=2⋅3=3⋅2.
\;\;\;\; 求 f f f 的前 n n n 项和。
\;\;\;\; 1 ≤ T ≤ 20 , 1 ≤ n ≤ 2 ∗ 1 0 7 1 \leq T \leq 20, 1 \leq n \leq 2*10^{7} 1≤T≤20,1≤n≤2∗107.
\;\;\;\; 欧拉筛的思路:每个数被其最小素因子标记。
\;\;\;\; 将一个数质因子分解: n = p 1 e 1 ⋅ p 2 e 2 ⋅ p 3 e 3 . . . n = p_{1}^{e_{1}} \cdot p_{2}^{e_{2}} \cdot p_{3}^{e_{3}}... n=p1e1⋅p2e2⋅p3e3... ,在其所有的指数 e 1 , e 2 , e 3 . . . e_{1},e_{2}, e_{3}... e1,e2,e3... 中:
\;\;\;\;\;\; 若 e i = 1 e_{i} =1 ei=1,那么 p i p_{i} pi 可以放在 a a a 或 b b b 中,对 f [ n ] f[n] f[n] 贡献为 × 2 \times2 ×2;
\;\;\;\;\;\; 若 e i = 2 e_{i} =2 ei=2,那么 p i p_{i} pi 必须拆开,一个放在 a a a 中,另一个放在 b b b 中,对 f [ n ] f[n] f[n] 贡献为 × 1 \times1 ×1;
\;\;\;\;\;\; 若 e i > 2 e_{i} >2 ei>2,那么 p i p_{i} pi 无论怎么拆分,在 a a a 或 b b b 中总会有平方数或其倍数,这时 f [ n ] = 0 f[n] = 0 f[n]=0.
/*
nero
https://nanti.jisuanke.com/t/A1956
c[i]记录最小质因子的指数
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define lson(u) (u<<1)
#define rson(u) (u<<1|1)
#define Pi acos(-1)
#define iINF 0x3f3f3f3f
#define lINF 0x3f3f3f3f3f3f3f
#define EPS 0.000000001
#define pii pair
typedef long long ll;
typedef unsigned long long ull;
const int MAXN = 20000005;
const ll Mod = 1000000007;
#define MOD(a, b) a>=b?a%b+b:a
int prime[MAXN], c[MAXN];
ll f[MAXN];
bool Isprime[MAXN];
void Init(){
int N = MAXN-5, cnt = 0;
f[1] = 1;
for(int i = 2; i <= N; i++){
if(!Isprime[i]) {
prime[++cnt] = i;
f[i] = 2;
c[i] = 1;
}
for(int j = 1; j <= cnt && (ll)i*prime[j] <= N; j++) {
int x = i*prime[j];
Isprime[x] = 1;
if(i%prime[j] == 0) {
c[x] = c[i] + 1;
if(c[x] == 2) {
// 指数为 2
f[x] = f[i/prime[j]];
}
else {
// 指数 > 3
f[x] = 0;
}
break;
}
else {
// 指数为 1
c[x] = 1; // WA c[x] = c[i]
f[x] = f[i] * 2;
}
}
}
for(int i = 1; i <= N; i++) {
f[i] += f[i-1];
}
}
int main() {
Init();
int T, n;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
printf("%lld\n", f[n]);
}
return 0;
}
/*
*/
\;\;\;\; 要求 ∑ i = 1 n a b = i \sum_{i=1}^{n}ab=i ∑i=1nab=i,即求 ∑ a b ≤ n \sum ab \leq n ∑ab≤n. 比如:当 n = 30 , a = 3 n=30, a=3 n=30,a=3 时, 30 / 3 = 10 30/3=10 30/3=10,即有 10 10 10 个 b ( 1 − 10 ) b(1-10) b(1−10) 满足条件,再删掉其中的平方数以及它们的倍数即可。
\;\;\;\; s u m [ i ] sum[i] sum[i] 表示前 i i i 数中有多少个数不含平方数因子, p [ i ] p[i] p[i] 表示第 i i i 个不含平方数因子的数, 则 a n s = ∑ s u m [ n / p i ] ans = \sum sum[n/p_{i}] ans=∑sum[n/pi].
/*
nero
https://nanti.jisuanke.com/t/A1956
bo[j]=0 表示数 j 不含平方数因子
sum[i] 表示前i个数里面有多少个数不含平方数因子
p[i] 表示第i个不含平方数因子的数
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define lson(u) (u<<1)
#define rson(u) (u<<1|1)
#define Pi acos(-1)
#define iINF 0x3f3f3f3f
#define lINF 0x3f3f3f3f3f3f3f
#define EPS 0.000000001
#define pii pair
#define MOD(a, b) a>=b?a%b+b:a
typedef long long ll;
typedef unsigned long long ull;
const int MAXN = 20000005;
const ll Mod = 1000000007;
int sum[MAXN], p[MAXN], cnt;
bool bo[MAXN];
void Init(){
int N = MAXN-5;
for(int i = 2; i <= N; i++){
ll x = i*i;
if(x > N) break;
for(int j = x; j <= N; j+=x) {
bo[j] = 1;
}
}
for(int i = 1; i <= N; i++) {
if(bo[i]) {
sum[i] = sum[i-1];
}
else {
p[++cnt] = i;
sum[i] = sum[i-1] + 1;
}
}
}
int main() {
Init();
int T, n, ans;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
ans = 0;
for(int i = 1; i <= cnt && p[i] <= n; i++) {
int idx = n/p[i];
ans += sum[idx];
}
printf("%lld\n", ans);
}
return 0;
}
/*
*/
参考:
ACM-ICPC 2018 南京赛区网络预赛 Sum(线性筛)
ACM-ICPC 2018 南京赛区网络预赛 J.sum
好久没有写博客,忽然发现有了不同语言的代码片,好评!