2021.08.03/04(约数个数、欧拉函数)

#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; #define int long long const int maxx=1e6+10; int a[maxx]; int s[maxx]={0},p[maxx]={0}; signed main(void){ int n; scanf("%lld",&n); for(int i=0;i<n;i++){ scanf("%lld",&a[i]); s[a[i]]++; } for(int i=1;i<maxx;i++){ for(int j=i;j<maxx;j+=i){ p[j]+=s[i]; } } for(int i=0;i<n;i++){ printf("%lld\n",p[a[i]]-1); } }
注:主要是通过一个很技巧性的东西就是先不管到底里面有谁,先存进去,然后1-1e6全部操作,毕竟没有的数存入的就是0不影响结果

#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; const int maxn = 10000001; bool vis[maxn]; // 0 为素数 1 为非素数 int tot, phi[maxn], prime[maxn]; void CalPhi() { vis[1] = 1, phi[1] = 1; for (int i = 2; i < maxn; ++i) { if (!vis[i]) prime[tot++] = i, phi[i] = i - 1; for (int j = 0; j < tot; ++j) { if (i * prime[j] > maxn) break; vis[i * prime[j]] = 1; if (i % prime[j] == 0) { phi[i * prime[j]] = phi[i] * prime[j]; break; } else phi[i * prime[j]] = phi[i] * (prime[j] - 1); } } } #define int long long const int mod=1e9+7; const int maxx=1e6+10; int p[maxx]; signed main(void){ int n; scanf("%lld",&n); CalPhi(); int sign=0; int ss=1; for(int i=0;i<tot;i++){ if(prime[i]>n){ break; } int p=prime[i]; int flag=0; for(int j=n/p;j;j/=p){//类似于算2是因数的 4是因数的 8是因数的 flag+=j; } ss*=(2*flag+1); ss%=mod; // printf("%lld\n",ss); } printf("%lld\n",ss); }
注:
1)遇见阶乘类的分解的问题,一定不要想着去求阶乘,因为阶乘太大了,最好也不要取余去挨个求,这样也会出现精度问题,一i的那个想起来直接用n联系prime[i]中用做步长,n不变,j=n用j去估算
2)
化简公式的技巧,再就是化简公式的时候一定要和已知挂钩,要研究已知数,不要用假设的x和y去扩大他们
3)约数的个数:写成素数相乘的格式,然后用组合数学,当然平方类的因为数大的原因最好是直接开一下然后记得在素数的指数上乘2就行