zoukankan      html  css  js  c++  java
  • ACM-ICPC 2018 南京赛区网络预赛 J题Sum(线性筛素数)

    题目链接https://nanti.jisuanke.com/t/30999

    参考自博客https://kuangbin.github.io/2018/09/01/2018-ACM-ICPC-Nanjing-online-J/

    题目中文

    •  1000毫秒
    •  512000K

    无方形整数是一个整数,除了1以外的任何平方数都不可分 这个数。例如,6 = 2 *3,6=2*3,6是无方形整数,但12 = 2 ^ 2*3,,因为2 ^ 2是正方形数。有些整数可以分解为两个无方形整数的乘积,可能有多种分解方式。例如,6=1·6=6·1=2·3=3·2,n=a*bn=b*a被认为是不同的。)是分解方式的数量n=a*b。问题在于计算

    输入

    第一行包含一个整数 ,表示的测试用例的数量。

    对于每个测试用例,第一行有一个整数 

    产量

    对于每个测试用例,打印答案 

    暗示

     

    样例输入复制

    2
    5
    8

    样例输出复制

    8
    14

     解题思路:首先我们对f(n)分析,我们知道对于任意一个数,我们都可以把他拆分成若干素因子乘积的形式如f(n)=p^x+q^y+……r^z,如果f(n)的素因子分解式子中,某个素因子的指数大于二,则f(n)就一定为0;比如f(8)=f(2^3)=0;

    如果f(n)非0,则f(n)的素因子的指数只能为1或者2了,如果该素因子的指数为1,则对结果的贡献度为2(即其余素因子分成两部分,可加入任意一边),如果该素因子的指数为1,则对结果的贡献度为1(其余素因子分成两部分,一边一个);

    所有如果单独求一个f(n)的话,只需要对n进行素因素分解。

    但是现在需要求12×10^7f(n), 我们需要进行递推。

    假如我们知道n的最小素因子是p的话,而且p的指数是x的话,即n=y*p^x.

    那么很显然,如果x == 1, 那么f(n)=2×f(y), 如果x == 2, 那么f(n)=f(y), 如果x > 2, 那么f(n)=0.

    然后这里就这要用线性筛素数了,而筛素数的同时记录每个最小的素因子。

    附上代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll maxn=2e7;
    int prime[maxn+7],minprime[maxn+7];
    ll cnt[maxn+7];
    //线性筛素数
    void getprime()
    {
        memset(prime,0,sizeof(prime));
        int tot=0;
        for(int i=2;i<=maxn;i++)
        {
            if(!prime[i])
            {
                prime[tot++]=i;
                minprime[i]=i;
            }
            for(int j=0;j<tot&&i*prime[j]<=maxn;j++)
            {
                prime[i*prime[j]]=1;
                minprime[i*prime[j]]=prime[j];
                if(i%prime[j]==0)
                break;
            }
        }
    }
    
    int main()
    {
        getprime();
        cnt[1]=1;
        for(int i=2;i<=maxn;i++)
        {
            int x=minprime[i];  //最小素因子
            if(i%(x*x*x)==0) cnt[i]=0;  //最小素因子指数大于2
            else if(i%(x*x)==0) cnt[i]=cnt[i/(x*x)]; //最小素因子指数等于2
            else cnt[i]=2*cnt[i/x];  //最小素因子指数为1
        }
        for (int i=2;i<=maxn;i++)
            cnt[i]+=cnt[i-1];
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n;
            scanf("%d",&n);
            printf("%lld
    ",cnt[n]);
        }
        return 0;
    }

      

     

     

  • 相关阅读:
    读理,妙句秒人秒事,二记
    读理,妙句秒人秒事,一记
    (原)DirectX11 深度测试(有点另类)
    游戏编程书籍推荐
    android入门-环境搭建
    Spring||Interview
    JSR-133内存模型手册
    JVM执行引擎
    HIbernate总结
    虚拟机类加载机制
  • 原文地址:https://www.cnblogs.com/zjl192628928/p/9580403.html
Copyright © 2011-2022 走看看