zoukankan      html  css  js  c++  java
  • 积性函数,线性筛入门 HDU

    HDU - 2879 HeHe

      题意:He[N]为[0,N1]范围内有多少个数满足式子x2x (mod N),HeHe[N]=He[1]××He[N]

      我是通过打表发现的he[x]=2k,k为x是质因子个数,不过这是可以通过积性函数证明的。

      关于积性函数的定义:

    对于正整数n的一个算术函数 f(n),若f(1)=1,且当a,b互质时,f(ab)=f(a)f(b),在数论上就称它为积性函数。若对于某积性函数 f(n) ,就算a, b不互质,也有f(ab)=f(a)f(b),则称它为完全积性的。

      引用证明,HDU 2879 HeHe (素数+积性函数及证明)

      知道了,he[x]=2k之后,接下来求hehe[n]其实就是求2k1+k2+...kn,具体实现上,有好几种方法。

      普通的埃氏筛,对于每个数它的每个质因子就在指数贡献一个了1,所以我们可以先把质数筛出来,然后再看n范围内包含有多少个这个质数的倍数。

     1 #include<cstdio>
     2 typedef long long ll;
     3 const int N=10000007;
     4 bool nop[N]={false};
     5 int pn,pri[N/10];
     6 void init()
     7 {
     8     pn=0;
     9     for(int i=2;i<N;i++)
    10     {
    11         if(!nop[i])
    12         {
    13             pri[pn++]=i;
    14             for(int j=i<<1;j<N;j+=i)
    15                 nop[j]=true;
    16         }
    17     }
    18 }
    19 ll pow(int b,int mod)
    20 {
    21     ll ans=1,a=2ll;
    22     while(b)
    23     {
    24         if(b&1)
    25             ans=(ans*a)%mod;
    26         a=(a*a)%mod;
    27         b>>=1;
    28     }
    29     return ans%mod;
    30 }
    31 int main()
    32 {
    33     init();
    34     int t,n,m;
    35     scanf("%d",&t);
    36     while(t--)
    37     {
    38         scanf("%d%d",&n,&m);
    39         int sum=0;
    40         for(int i=0;i<pn&&pri[i]<=n;i++)
    41             sum+=n/pri[i];
    42         printf("%lld
    ",pow(sum,m));
    43     }
    44     return 0;
    45 }
    埃氏筛

      第二个线性筛(欧拉筛),为什么欧拉筛是O(n),,可以看这个证明线性筛(欧拉筛)然后,前面有证明he是积性函数,所有我们就可以通过欧拉筛先把he预处理处理。

    #include<cstdio>
    typedef long long ll;
    const int N=10000007;
    bool nop[N]={false};
    int pn,pri[N/10],he[N];
    void init()
    {
        pn=0;
        for(int i=2;i<N;i++)
        {
            if(!nop[i])
            {
                he[i]=1;//he[i]=2^1, 
                pri[pn++]=i;
            }
            for(int j=0;j<pn&&1ll*i*pri[j]<N;j++)
            {
                int temp=i*pri[j];
                nop[temp]=true;
                if(i%pri[j]==0)
                {
                    he[temp]=he[i];//temp的质因子数跟i相同 
                    break;
                }
                he[temp]=he[i]+he[pri[j]];//f[a*b]=f[a]*fa[b],
                //这里he保存的是指数,所以是+ 
            }
        }
    }
    ll pow(int b,int mod)
    {
        ll ans=1,a=2ll;
        while(b)
        {
            if(b&1)
                ans=(ans*a)%mod;
            a=(a*a)%mod;
            b>>=1;
        }
        return ans%mod;
    }
    int main()
    {
        init();
        int t,n,m;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
            int sum=0;
            for(int i=1;i<=n;i++)
                sum+=he[i];
            printf("%lld
    ",pow(sum,m));
        }
        return 0;
    }
    欧拉筛
  • 相关阅读:
    公用表表达式(CTE)的递归调用
    c# 如何让tooltip显示文字换行
    实战 SQL Server 2008 数据库误删除数据的恢复
    SQL SERVER数据库中 是否可以对视图进行修改删除
    asp.net中实现文件批量上传
    sql server 2008学习2 文件和文件组
    sql server 2008学习3 表组织和索引组织
    sql server 2008学习4 设计索引的建议
    sql server 2008学习10 存储过程
    .net 调用 sql server 自定义函数,并输出返回值
  • 原文地址:https://www.cnblogs.com/LMCC1108/p/11089153.html
Copyright © 2011-2022 走看看