码迷,mamicode.com
首页 > 其他好文 > 详细

积性函数,线性筛入门 HDU - 2879

时间:2019-06-26 13:28:37      阅读:75      评论:0      收藏:0      [点我收藏+]

标签:cli   hdu   线性   ssis   des   show   sum   lan   lld   

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\n",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\n",pow(sum,m));
    }
    return 0;
}
欧拉筛

 

积性函数,线性筛入门 HDU - 2879

标签:cli   hdu   线性   ssis   des   show   sum   lan   lld   

原文地址:https://www.cnblogs.com/LMCC1108/p/11089153.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!