2018年ACM-ICPC - 南京网络赛J:Sum【欧拉线性筛】

题目:

戳这里~~~

题意:

一个数的square-free是它的所有因子中不包含有平方数因子分解的个数(1除外),例如:12可以分解为 4 * 3,但4是平方数,所以f(12) 中就不包括3和4,题意要求\large \sum_{i=1}^{n}{f(n)}

题解: 

对于一个数n,我们可以先分解它的质因子,然后考虑将所有质因子分成两组,考察有多少种不同的分组方式,比如:30 有2,3,5的质因子各一个,那么可以分成(1,30),(2,15),(3,10),(5,6),则 f(30) = 8;设n = a1^p1 + a2^p2 + ...... + ai^pi(ai为质数)。

1)如果有一个pi > 3,那么 f(n) = 0,无论怎么分组,根据鸽巢原理,至少有两个在一边,不符合题意。

2)如果pi =2,ai这两个质因子一定是一边一个。

3)所有pi = 1;那么f(n) = 2^(质因子的个数),可以用组合数来证明:分组时左边可以选0个,右边n个,左边1个,右边n-1个.....,左边+右边也就是   \large C_n^{0}+C_n^{1}+C_n^{2}+.....+C_n^{n}=2^n

代码:

#include<iostream>
#include<string.h>
using namespace std;
const int maxn = 2e7+7;
int phi[maxn];           //记录每一个数的f[n]
int prime[maxn];           
bool vis[maxn];
void Eular()             //欧拉筛模板
{
    memset(vis,true,sizeof(vis));
    phi[1]=1;
    int p=0;
    for(int i=2;i<maxn;i++)
    {
        if(vis[i])
        {
            phi[i]=2;     //质数只有两个因子,且不含平方数
            prime[p++]=i;
        }
        for(int j=0;j<p&&i*prime[j]<maxn;j++)
        {
            int tep = i*prime[j];
            vis[tep] = false;
            if(i%prime[j])    //i和prime[j]互质,相当于tep多了一个质因子prime[j]
                phi[tep]=phi[i]*2;
            else if(i%(prime[j]*prime[j])==0) //i含有2个prime[j],则tep含有3个
                phi[tep] = 0; 
            else
            {
                phi[tep]=phi[i]/2;  //tep中有两个prime[j],好比2,3,5多了一个2,模拟一下就知道phi[i]的分组重复了一遍
                break;
            }
        }
    }
}
int main()
{
    int t,n;
    Eular();
    for(int i=2;i<maxn-1;i++)
        phi[i]+=phi[i-1];
    while(cin>>t)
    {
        while(t--)
        {
            cin>>n;
            cout<<phi[n]<<endl;
        }
    }
    return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值