数论--筛法变形--ACM-ICPC 2018 南京赛区网络预赛 J.Sum

https://nanti.jisuanke.com/t/30999

f[i]表示将i分解为2个数相乘的方案数,i = a*b,且a,b均不能有平方因子。

求f[i]前缀和

n = p1^a1 * p2^a2 * p3^a3 * ... * pk^ak

= a * b

若a1 = 1,则a可能有p1,可能没有,f[n] = f[n / p1] * 2

a1 = 2,则a必须选p1(a,b一人一个),f[n] = f[n / (p1 * p1)]

a1 > 2,无论怎么分一边都有平方因子,f[n] = 0

 

筛法

1.p为质数,f[p] = 2

2.开始筛i * prime[j]

若i % prime[j] != 0,则i * prime[j]中只有一个prime[j],(a1 = 1),f[i * prime[j]] = f[i] * 2

若i % (prime[j] * prime[j]) == 0,则i * prime[j]中prime[j]对应指数a1 > 2,f[i * prime[j]] = 0

否则,若i % prime[j] == 0,则i * prime[j]中恰好有2个prime[j],a1 = 2,f[i * prime[j]] = f[i]


#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 2e7 + 1;
bool noprime[maxn];
int prime[maxn / 10],sz = 0;
long long f[maxn];

void solve()
{
    f[1] = 1;
    for (int i = 2; i < maxn; i ++) {
        if(!noprime[i]) {prime[sz ++] = i;f[i] = 2;  }
       
        for (int j = 0; j < sz && i * prime[j] < maxn; j ++) {

            noprime[i * prime[j]] = true;
            if(i % (1ll * prime[j] * prime[j]) == 0){
                long long t = 1ll * i * prime[j] * prime[j];
               if(t < maxn) f[t] = 0;
            }
            else if(i % prime[j] ==  0){
                f[1ll * i * prime[j]] = f[i / prime[j]];
                break;
            }
            else{
                f[i * prime[j]] = f[i] * 2;
            }
        }
    }
    for (int i = 2; i < maxn; i ++) {
        f[i] += f[i - 1];
    }
}
int main()
{
    solve();
    int T;scanf("%d",&T);
    int n;
    while (T --) {
        scanf("%d",&n);
        printf("%lld\n",f[n]);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值