线筛
o(n)的复杂度,筛出各种神奇。
bzoj2190仪仗队
思路:线筛求欧拉函数。
#include<iostream> #include<cstdio> using namespace std; int phi[40001]={0},prime[40001]={0}; bool flag[40001]={false}; void work(int n) { int i,j; for (i=2;i<=n;++i) { if (!flag[i]) { ++prime[0];prime[prime[0]]=i;phi[i]=i-1; } for (j=1;j<=prime[0]&&i*prime[j]<=n;++j) { flag[prime[j]*i]=true; if (i%prime[j]==0) { phi[i*prime[j]]=phi[i]*prime[j];break; } else phi[i*prime[j]]=phi[i]*(prime[j]-1); } } } int main() { int n,ans=0,i; scanf("%d",&n); work(n); for (i=2;i<n;++i) ans+=phi[i]*2; ans+=3; if (n==1) printf("1\n"); else printf("%d\n",ans); }
某次题目:
题目大意:输入n,求多少个正整数对x,y满足(1/x)+(1/y)=1/(n!)。
思路:对原式进行数学化简:n!=xy/(x+y),再化简一下:x=yn!/(y-n!),设a=n!,有x=ya/(y-a),令b=y-a,x=a(a+b)/b=a^2/b+a。因为x、y、a、b都是整数,所以b是a^2的约数,所以答案就是a^2约数个数个。(code中用了一个小技巧,穷举质因数,求质因数在n!中出现的个数,再共享给答案。可能会快。)
#include<iostream> #include<cstdio> #define P 1000000007 #define maxnode 1000005 using namespace std; bool flag[maxnode]={false}; int prime[maxnode]={0}; void yu(int n) { int i,j; for (i=2;i<=n;++i) { if (!flag[i]) prime[++prime[0]]=i; for (j=1;j<=prime[0]&&i*prime[j]<=n;++j) { flag[i*prime[j]]=true; if (i%prime[j]==0) break; } } } int main() { long long ans; int i,j,t,n,k; scanf("%d",&n); yu(n);ans=1; for (i=1;i<=prime[0];++i) { k=0; for (j=1;j*prime[i]<=n;++j) { t=j*prime[i]; while(t%prime[i]==0) { ++k;t/=prime[i]; } } ans=(ans*(long long)(2*k+1))%P; } printf("%d\n",(int)ans); }