1.若N=p1^(c1)+p2^(c2)+p3^(c3)+..... p为素数
约数个数为(c1+1)*(c2+1)*(c3+1)*......
2. 1到N中 所以约数和
3.0<=N<=2*1e9 约数个数最多的个数为1600
1.轻拍牛头
题意:全部数中除自己外有多少个因数,重复也算
用到性质二算时间复杂度 nlogn
- #include
- using namespace std;
- const int N=1000010;
- int n;
- int a[N],cnt[N],s[N];
- int main()
- {
- scanf("%d",&n);
- for(int i=0;i
- {
- scanf("%d",&a[i]);
- cnt[a[i]]++;
- }
- for(int i=1;i
- for(int j=i;j
- {
- s[j]+=cnt[i];
- }
- for(int i=0;i
- printf("%d\n",s[a[i]]-1);
- return 0;
- }
2.樱花


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

- #include
- using namespace std;
- typedef long long ll;
- const int N=1e6+10,mod=1e9+7;
- int prime[N],cnt;
- bool st[N];
- void init(int n)//筛质数
- {
- for(int i=2;i<=n;i++)
- {
- if(!st[i]) prime[cnt++]=i;
- for(int j=0;prime[j]*i<=n;j++)
- {
- st[prime[j]*i]=true;
- if(i%prime[j]==0) break;
- }
- }
- }
- int main()
- {
- int n;
- cin>>n;
- init(n);
- int res=1;
- for(int i=0;i
//枚举质数 - {
- int p=prime[i];
- int s=0;
- for(int j=n;j;j/=p) s+=j/p;//求p的次方
- res=(ll)res*(2*s+1)%mod;//答案乘上个数
- }
- cout<
- return 0;
- }
3.反素数
相当于求小于n中约数最多的数的最小数
因为不同的质因子最多有9个,因为2*3*5*7*11*13*17*19*23*29>2e9,所以只需前9个不同质因子即可构成所有的约数
然后2^31>2e9,所以最多枚举到30次方即可,用dfs暴搜来求

- #include
- using namespace std;
- int primes[]={2,3,5,7,11,13,17,19,23};
- int maxd,number;
- int n;
- typedef long long ll;
- void dfs(int u,int last,int p,int s)
- {
- if(s>maxd||s==maxd&&p
- {
- maxd=s;
- number=p;
- }
- if(u==9) return ;
- for(int i=1;i<=last;i++)
- {
- if((ll)p*primes[u]>n) break;
- p*=primes[u];
- dfs(u+1,i,p,s*(i+1));
- }
- }
- int main()
- {
- cin>>n;
- dfs(0,30,1,1);
- cout<
- return 0;
- }
4.Hankson的趣味题
- #include
- using namespace std;
- typedef long long ll;
- const int N=1e5+10;
- int prime[N],cnt;
- bool st[N];
- int a,b,c,d;
- int fcnt;
- struct
- {
- int p,s;
- }f[1601];//存质因数跟次幂
- int divide[1601],dcnt;//存约数
- int gcd(int a,int b)//求最大公约数
- {
- return b?gcd(b,a%b):a;
- }
- void dfs(int u,int p)//枚举到第u个 当前的约数是p
- {
- if(u==fcnt)//假如枚举完了,这是个合法的约数
- {
- divide[dcnt++]=p;
- return;
- }
- for(int i=0;i<=f[u].s;i++)//枚举所有次幂
- {
- dfs(u+1,p);
- p*=f[u].p;//更新一下p
- }
- }
- void init(int n)//线性筛
- {
- for(int i=2;i<=n;i++)
- {
- if(!st[i]) prime[cnt++]=i;
- for(int j=0;prime[j]*i<=n;j++)
- {
- st[prime[j]*i]=true;
- if(i%prime[j]==0) break;
- }
- }
- }
- void solve()
- {
- fcnt=dcnt=0;
- int res=0;
- cin>>a>>b>>c>>d;
- int t=d;
- //将d进行分解质因式
- for(int i=0;prime[i]<=t/prime[i];i++)//枚举所有质因子
- {
- int p=prime[i];
- if(t%p==0)
- {
- int s=0;
- while(t%p==0) t/=p,s++;
- f[fcnt++]={p,s};//记录这个质因数跟幂次
- }
- }
- if(t>1) f[fcnt++]={t,1};//假如有剩余,也存起来
- dfs(0,1);//暴力搜索所有约数
- for(int i=0;i
//枚举d的所有约数 - {
- int x=divide[i];
- if(gcd(a,x)==b&&(ll)c*x/gcd(x,c)==d) res++;//假如满足条件则答案++
- }
- cout<
- }
- int main()
- {
- init(100000);//预处理出来质数
- int T;
- cin>>T;
- while(T--) solve();
- return 0;
- }
欧拉函数
1到N中和N互质的数的个数

模板
- void init(int n)//欧拉筛
- {
- phi[1]=1;
- for(int i=2;i<=n;i++)
- {
- if(!st[i])
- {
- prime[cnt++]=i;
- pri[i]=i-1;
- }
- for(int j=0;prime[j]*i<=n;j++)
- {
- st[prime[j]*i]=true;
- if(i%prime[j]==0)
- {
- phi[i*prime[j]]=phi[i]*prime[j];
- break;
- }
- phi[i*prime[j]]=phi[i]*(prime[j]-1);
- }
- }
- }
1.可见的点
假如[x,y]x与y不互质,则必能约成最简【x/d,y/d】所以[x,y]这个点会被[x/d,y/d]
这个点挡住,所以只要求与x互质的y的个数加起来就是答案了,因为两边互质的数关于y=x对称,则只需y=x下面的互质数在×2就为答案,因为y=x也有一条则最终的答案+1
- #include
- using namespace std;
- typedef long long ll;
- const int N=1e5+10;
- int prime[N],cnt;
- bool st[N];
- int phi[N];
- void init(int n)//欧拉筛
- {
- phi[1]=1;
- for(int i=2;i<=n;i++)
- {
- if(!st[i])
- {
- prime[cnt++]=i;
- phi[i]=i-1;
- }
- for(int j=0;prime[j]*i<=n;j++)
- {
- st[prime[j]*i]=true;
- if(i%prime[j]==0)
- {
- phi[i*prime[j]]=phi[i]*prime[j];
- break;
- }
- phi[i*prime[j]]=phi[i]*(prime[j]-1);
- }
- }
- }
- int main()
- {
- init(1010);//预处理出来欧拉函数
- int T;
- cin>>T;
- for(int i=1;i<=T;i++)
- {
- int n,res=0;
- cin>>n;
- for(int i=1;i<=n;i++) res+=2*phi[i];//求答案
- printf("%d %d %d\n",i,n,res+1);
- }
- return 0;
- }
2.最大公约数
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之间的互质数对个数,所以提前预处理出来前缀和即可
- #include
- using namespace std;
- typedef long long ll;
- const int N=1e7+10;
- int prime[N],cnt;
- bool st[N];
- int phi[N];
- ll s[N];//记录欧拉函数的前缀和
- void init(int n)//欧拉筛
- {
- phi[1]=0;//下标题目从1开始
- for(int i=2;i<=n;i++)
- {
- if(!st[i])
- {
- prime[cnt++]=i;
- phi[i]=i-1;
- }
- for(int j=0;prime[j]*i<=n;j++)
- {
- st[prime[j]*i]=true;
- if(i%prime[j]==0)
- {
- phi[i*prime[j]]=phi[i]*prime[j];
- break;
- }
- phi[i*prime[j]]=phi[i]*(prime[j]-1);
- }
- }
- phi[1]=0;
- for(int i=1;i<=n;i++) s[i]=s[i-1]+phi[i];//处理出来欧拉数的前缀和
- }
- int main()
- {
- int n;
- ll res=0;
- cin>>n;
- init(n);//欧拉筛
- for(int i=0;i
//枚举所有的质数d - {
- int d=prime[i];
- res+=s[n/d]*2+1;//答案加上n/d的互质数队,跟上一题一样
- }
- printf("%lld\n",res);
- return 0;
- }
-
相关阅读:
怎么统计 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