• 约数个数和欧拉函数


    1.若N=p1^(c1)+p2^(c2)+p3^(c3)+..... p为素数

       约数个数为(c1+1)*(c2+1)*(c3+1)*......

     2. 1到N中 所以约数和\sum_{i=1}^{N}f(i)=NlogN

    3.0<=N<=2*1e9 约数个数最多的个数为1600


    1.轻拍牛头

    信息学奥赛一本通(C++版)在线评测系统 

    题意:全部数中除自己外有多少个因数,重复也算

    用到性质二算时间复杂度 nlogn

    1. #include
    2. using namespace std;
    3. const int N=1000010;
    4. int n;
    5. int a[N],cnt[N],s[N];
    6. int main()
    7. {
    8. scanf("%d",&n);
    9. for(int i=0;i
    10. {
    11. scanf("%d",&a[i]);
    12. cnt[a[i]]++;
    13. }
    14. for(int i=1;i
    15. for(int j=i;j
    16. {
    17. s[j]+=cnt[i];
    18. }
    19. for(int i=0;i
    20. printf("%d\n",s[a[i]]-1);
    21. return 0;
    22. }

    2.樱花

    信息学奥赛一本通(C++版)在线评测系统

     

     

    等价于求(n!)^2的约数个数 然后就是上一节的阶乘分解的拓展

     

     

    1. #include
    2. using namespace std;
    3. typedef long long ll;
    4. const int N=1e6+10,mod=1e9+7;
    5. int prime[N],cnt;
    6. bool st[N];
    7. void init(int n)//筛质数
    8. {
    9. for(int i=2;i<=n;i++)
    10. {
    11. if(!st[i]) prime[cnt++]=i;
    12. for(int j=0;prime[j]*i<=n;j++)
    13. {
    14. st[prime[j]*i]=true;
    15. if(i%prime[j]==0) break;
    16. }
    17. }
    18. }
    19. int main()
    20. {
    21. int n;
    22. cin>>n;
    23. init(n);
    24. int res=1;
    25. for(int i=0;i//枚举质数
    26. {
    27. int p=prime[i];
    28. int s=0;
    29. for(int j=n;j;j/=p) s+=j/p;//求p的次方
    30. res=(ll)res*(2*s+1)%mod;//答案乘上个数
    31. }
    32. cout<
    33. return 0;
    34. }

     3.反素数

    198. 反素数 - AcWing题库

    相当于求小于n中约数最多的数的最小数

    因为不同的质因子最多有9个,因为2*3*5*7*11*13*17*19*23*29>2e9,所以只需前9个不同质因子即可构成所有的约数

    然后2^31>2e9,所以最多枚举到30次方即可,用dfs暴搜来求

     

    1. #include
    2. using namespace std;
    3. int primes[]={2,3,5,7,11,13,17,19,23};
    4. int maxd,number;
    5. int n;
    6. typedef long long ll;
    7. void dfs(int u,int last,int p,int s)
    8. {
    9. if(s>maxd||s==maxd&&p
    10. {
    11. maxd=s;
    12. number=p;
    13. }
    14. if(u==9) return ;
    15. for(int i=1;i<=last;i++)
    16. {
    17. if((ll)p*primes[u]>n) break;
    18. p*=primes[u];
    19. dfs(u+1,i,p,s*(i+1));
    20. }
    21. }
    22. int main()
    23. {
    24. cin>>n;
    25. dfs(0,30,1,1);
    26. cout<
    27. return 0;
    28. }

    4.Hankson的趣味题

    200. Hankson的趣味题 - AcWing题库

    1. #include
    2. using namespace std;
    3. typedef long long ll;
    4. const int N=1e5+10;
    5. int prime[N],cnt;
    6. bool st[N];
    7. int a,b,c,d;
    8. int fcnt;
    9. struct
    10. {
    11. int p,s;
    12. }f[1601];//存质因数跟次幂
    13. int divide[1601],dcnt;//存约数
    14. int gcd(int a,int b)//求最大公约数
    15. {
    16. return b?gcd(b,a%b):a;
    17. }
    18. void dfs(int u,int p)//枚举到第u个 当前的约数是p
    19. {
    20. if(u==fcnt)//假如枚举完了,这是个合法的约数
    21. {
    22. divide[dcnt++]=p;
    23. return;
    24. }
    25. for(int i=0;i<=f[u].s;i++)//枚举所有次幂
    26. {
    27. dfs(u+1,p);
    28. p*=f[u].p;//更新一下p
    29. }
    30. }
    31. void init(int n)//线性筛
    32. {
    33. for(int i=2;i<=n;i++)
    34. {
    35. if(!st[i]) prime[cnt++]=i;
    36. for(int j=0;prime[j]*i<=n;j++)
    37. {
    38. st[prime[j]*i]=true;
    39. if(i%prime[j]==0) break;
    40. }
    41. }
    42. }
    43. void solve()
    44. {
    45. fcnt=dcnt=0;
    46. int res=0;
    47. cin>>a>>b>>c>>d;
    48. int t=d;
    49. //将d进行分解质因式
    50. for(int i=0;prime[i]<=t/prime[i];i++)//枚举所有质因子
    51. {
    52. int p=prime[i];
    53. if(t%p==0)
    54. {
    55. int s=0;
    56. while(t%p==0) t/=p,s++;
    57. f[fcnt++]={p,s};//记录这个质因数跟幂次
    58. }
    59. }
    60. if(t>1) f[fcnt++]={t,1};//假如有剩余,也存起来
    61. dfs(0,1);//暴力搜索所有约数
    62. for(int i=0;i//枚举d的所有约数
    63. {
    64. int x=divide[i];
    65. if(gcd(a,x)==b&&(ll)c*x/gcd(x,c)==d) res++;//假如满足条件则答案++
    66. }
    67. cout<
    68. }
    69. int main()
    70. {
    71. init(100000);//预处理出来质数
    72. int T;
    73. cin>>T;
    74. while(T--) solve();
    75. return 0;
    76. }

    欧拉函数

    1到N中和N互质的数的个数

    模板

    1. void init(int n)//欧拉筛
    2. {
    3. phi[1]=1;
    4. for(int i=2;i<=n;i++)
    5. {
    6. if(!st[i])
    7. {
    8. prime[cnt++]=i;
    9. pri[i]=i-1;
    10. }
    11. for(int j=0;prime[j]*i<=n;j++)
    12. {
    13. st[prime[j]*i]=true;
    14. if(i%prime[j]==0)
    15. {
    16. phi[i*prime[j]]=phi[i]*prime[j];
    17. break;
    18. }
    19. phi[i*prime[j]]=phi[i]*(prime[j]-1);
    20. }
    21. }
    22. }

     1.可见的点

    201. 可见的点 - AcWing题库

    假如[x,y]x与y不互质,则必能约成最简【x/d,y/d】所以[x,y]这个点会被[x/d,y/d]

    这个点挡住,所以只要求与x互质的y的个数加起来就是答案了,因为两边互质的数关于y=x对称,则只需y=x下面的互质数在×2就为答案,因为y=x也有一条则最终的答案+1

    1. #include
    2. using namespace std;
    3. typedef long long ll;
    4. const int N=1e5+10;
    5. int prime[N],cnt;
    6. bool st[N];
    7. int phi[N];
    8. void init(int n)//欧拉筛
    9. {
    10. phi[1]=1;
    11. for(int i=2;i<=n;i++)
    12. {
    13. if(!st[i])
    14. {
    15. prime[cnt++]=i;
    16. phi[i]=i-1;
    17. }
    18. for(int j=0;prime[j]*i<=n;j++)
    19. {
    20. st[prime[j]*i]=true;
    21. if(i%prime[j]==0)
    22. {
    23. phi[i*prime[j]]=phi[i]*prime[j];
    24. break;
    25. }
    26. phi[i*prime[j]]=phi[i]*(prime[j]-1);
    27. }
    28. }
    29. }
    30. int main()
    31. {
    32. init(1010);//预处理出来欧拉函数
    33. int T;
    34. cin>>T;
    35. for(int i=1;i<=T;i++)
    36. {
    37. int n,res=0;
    38. cin>>n;
    39. for(int i=1;i<=n;i++) res+=2*phi[i];//求答案
    40. printf("%d %d %d\n",i,n,res+1);
    41. }
    42. return 0;
    43. }

    2.最大公约数

    220. 最大公约数 - AcWing题库

    1 - N中gcd(a,b)=素数d,则gcd(a/d,b/d)=1,则a/d,b/d互质 则相当于在1 - N/d中 GCD(x,y)=1的个数

    x,y属于(1~n/d)则映射到二维坐标就跟上一题的求法一样了,就问1~n/d之间的互质数对个数,所以提前预处理出来前缀和即可

    1. #include
    2. using namespace std;
    3. typedef long long ll;
    4. const int N=1e7+10;
    5. int prime[N],cnt;
    6. bool st[N];
    7. int phi[N];
    8. ll s[N];//记录欧拉函数的前缀和
    9. void init(int n)//欧拉筛
    10. {
    11. phi[1]=0;//下标题目从1开始
    12. for(int i=2;i<=n;i++)
    13. {
    14. if(!st[i])
    15. {
    16. prime[cnt++]=i;
    17. phi[i]=i-1;
    18. }
    19. for(int j=0;prime[j]*i<=n;j++)
    20. {
    21. st[prime[j]*i]=true;
    22. if(i%prime[j]==0)
    23. {
    24. phi[i*prime[j]]=phi[i]*prime[j];
    25. break;
    26. }
    27. phi[i*prime[j]]=phi[i]*(prime[j]-1);
    28. }
    29. }
    30. phi[1]=0;
    31. for(int i=1;i<=n;i++) s[i]=s[i-1]+phi[i];//处理出来欧拉数的前缀和
    32. }
    33. int main()
    34. {
    35. int n;
    36. ll res=0;
    37. cin>>n;
    38. init(n);//欧拉筛
    39. for(int i=0;i//枚举所有的质数d
    40. {
    41. int d=prime[i];
    42. res+=s[n/d]*2+1;//答案加上n/d的互质数队,跟上一题一样
    43. }
    44. printf("%lld\n",res);
    45. return 0;
    46. }

  • 相关阅读:
    怎么统计 20 亿用户的登录状态 | bitmap
    Today‘s web RPC案例
    MCE | 肿瘤微环境在癌症中的作用
    算法 - 正方形数量
    jmeter
    Ubuntu 升级cuda版本与切换
    现代 CSS 之高阶图片渐隐消失术
    微信小程序 npm构建+vant-weaap安装
    【Python 实战基础】Pandas如何对Categorical类型字段数据统计
    聊聊 GPU 产品选型那些事
  • 原文地址:https://blog.csdn.net/lee_14141/article/details/127631834