积性函数,线性筛入门 HDU - 2879
Posted lmcc1108
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了积性函数,线性筛入门 HDU - 2879相关的知识,希望对你有一定的参考价值。
HDU - 2879 HeHe
题意:He[N]为[0,N−1]范围内有多少个数满足式子x2≡x (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的主要内容,如果未能解决你的问题,请参考以下文章