HDU - 2879HeHe
题意: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; }
欧拉筛
原文地址:https://www.cnblogs.com/LMCC1108/p/11089153.html
时间: 2024-11-08 02:02:48