目录
基本定理的推论
- N的正约数个数为
- N的所有正约数的和为
求1-n地正约数集合——倍数法
vector<int> e[maxn];
int n;
void solve(int n) {
for(int i=1;i<=n;i++)
for(int j=1;j<=n/i;j++)
e[i*j].push_back(i);
for(int i=1;i<=n;i++) {
for(int j=0;j<e[i].size();j++)
cout<<e[i][j]<<" ";
puts("");
}
}
CH3201 Hankson的趣味题
题目链接
题意
有n个询问,先给定四个自然数a、b、c、d,然后求有多少个x满足 gcd(x,a)=b, lcm(x,c) = d。
题解
90分写法:根据lcm(x,c)=d,可以推出x一定是d/c的倍数(根据gcd*lcm=x*d求得),这里就不详细叙述了。
100分写法:gcd(a,x)=b => gcd(a/b,x/b)=1,lcm也是同理,同样根据gcd*lcm=x*d,可以求出gcd(d/c,d/x)=1,因为x一定是d的约数,而求约数可以先求2~sqrt(d)所有与d不互质的数,然后依次判断(注意,n/i是另一个不互素的数,要考虑i!=x/i的情况)
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <cmath>
using namespace std;
#define INIT(x) memset(x,0,sizeof(x))
#define eps 1e-8
#define next next_
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x7fffffff;
const int inf = 0x3f3f3f3f;
const int maxn = 200005;
const int N = 105;
inline void read(int &x) {
int f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
int t,a,b,c,d;
int gcd(int a,int b) {
if(b==0) return a;
return gcd(b,a%b);
}
int main()
{
cin>>t;
while(t--) {
cin>>a>>b>>c>>d;
int ans = 0;
int temp = d/c;
for(int i=1;i<=sqrt(d);i++) {
if(d%i==0) {
if(i%b==0)
if(gcd(d/c,d/i)==1)
if(gcd(a/b,i/b)==1)
ans++;
int x = d/i;
if(x!=i) {
if(x%b==0)
if(gcd(d/c,d/x)==1)
if(gcd(a/b,x/b)==1) {ans++;}
}
}
}
cout<<ans<<endl;
}
return 0;
}
欧拉定理
欧拉函数
若, 则
求单个数的欧拉函数
int phi(int n) {
int res = n;
for(int i=2;i<=sqrt(n);i++)
if(n%i==0) {
res = res/i*(i-1);
while(n%i==0) n/=i;
}
if(n>1) res = res/n*(n-1); //可能出现n为质数
return res;
}
求欧拉函数表 O(N logN)
void euler(int n) {
for(int i = 2; i <= n; i++) phi[i] = i;
for(int i = 2; i <= n; i++) {
if (phi[i] == i)
for (int j = i; j<= n; j+= i)
phi[j] = phi[j] / i * (i - 1);
}
}
求欧拉函数表 O(N)
void euler(int n) {
INIT(vis);
for(int i=2;i<=n;i++) {
if(!vis[i]) {
prime[++tot] = i;
vis[i] = i;
phi[i] = i-1;
}
for(int j=1;i*prime[j]<=n;j++) {
vis[i*prime[j]] = prime[j];
if(i%prime[j]) {
phi[i*prime[j]] = phi[i] * (prime[j]-1);
}else {
phi[i*prime[j]] = phi[i] * prime[j];
break;
}
}
}
}