[关闭]
@y20070316 2017-04-08T14:49:12.000000Z 字数 2550 阅读 1515

杜教筛

专题练习 初等数论 杜教筛



Problem List

【51nod 1244】莫比乌斯函数之和

  1. #include <cstdio>
  2. #include <map>
  3. using namespace std;
  4. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  5. #define LL long long
  6. const int N=5000000;
  7. int v[N+5],pri[500000],tot;
  8. int mu[N+5];
  9. map<LL,LL> s;
  10. LL Query(LL n) {
  11. if (n<=N) return mu[n];
  12. if (s.count(n)) return s[n];
  13. LL ans=1;
  14. for (LL l=2,r;l<=n;l=r+1) {
  15. r=n/(n/l);
  16. ans-=(r-l+1)*Query(n/l);
  17. }
  18. return s[n]=ans;
  19. }
  20. int main(void) {
  21. #ifndef ONLINE_JUDGE
  22. freopen("sdchr.in","r",stdin);
  23. #endif
  24. v[1]=mu[1]=1;
  25. F(i,2,N) {
  26. if (!v[i]) pri[++tot]=i,mu[i]=-1;
  27. F(j,1,tot) {
  28. if (i*pri[j]>N) break;
  29. v[i*pri[j]]=1;
  30. if (i%pri[j]!=0) mu[i*pri[j]]=-mu[i]; else break;
  31. }
  32. }
  33. F(i,1,N) mu[i]+=mu[i-1];
  34. LL a,b; scanf("%lld%lld",&a,&b);
  35. LL ansL=Query(a-1);
  36. printf("%lld\n",Query(b)-ansL);
  37. return 0;
  38. }

【51nod 1239】欧拉函数求和




实现:

  1. inline int binom2(LL n) {
  2. return (n%2==0) ? ((n/2)%L) * ((n+1)%L) %L : ((n+1)/2)%L * (n%L) %L;
  3. }

  总之如果 AB 是两个运算的整体,那么写成 (A) * (B) % L

  1. #include <cstdio>
  2. #include <map>
  3. using namespace std;
  4. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  5. #define LL long long
  6. const int N=5000000;
  7. const int L=(int)1e9+7;
  8. int v[N+5],pri[500000],tot;
  9. int phi[N+5];
  10. map<LL,int> s;
  11. int Query(LL n) {
  12. if (n<=N) return phi[n];
  13. if (s.count(n)) return s[n];
  14. int ans=( n%2==0 ? (n/2)%L * ((n+1)%L) %L : ((n+1)/2%L) * (n%L) %L );
  15. for (LL l=2,r;l<=n;l=r+1) {
  16. r=n/(n/l);
  17. ans=(ans- ((r-l+1)%L) * Query(n/l) %L )%L;
  18. }
  19. return s[n]=(ans+L)%L;
  20. }
  21. int main(void) {
  22. #ifndef ONLINE_JUDGE
  23. freopen("sdchr.in","r",stdin);
  24. #endif
  25. v[1]=phi[1]=1;
  26. F(i,2,N) {
  27. if (!v[i]) pri[++tot]=i,phi[i]=i-1;
  28. F(j,1,tot) {
  29. if (i*pri[j]>N) break;
  30. v[i*pri[j]]=1;
  31. if (i%pri[j]!=0) phi[i*pri[j]]=phi[i]*phi[pri[j]];
  32. else { phi[i*pri[j]]=phi[i]*pri[j]; break; }
  33. }
  34. }
  35. F(i,1,N) phi[i]=(phi[i]+phi[i-1])%L;
  36. LL n; scanf("%lld",&n);
  37. printf("%d\n",Query(n));
  38. return 0;
  39. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注