CF1717E. Madoka and The Best University(数论)

CF1717E. Madoka and The Best University

数论真有意思啊哈!

解题思路

\(a,b,c\) 中最特殊的是 \(c\),因为 \(a,b\) 是对称轮换的。所以我们考虑枚举每个 \(c\)。范围为 \([1,n-2]\)

为了方便表示,我们令 \(g=\gcd(a,b)\)

我们观察 \(g\) 最基本的性质,也就是 \(g\) 能整除 \(a,b\),那么以为着 \(g\mid a+b\)。由于 \(a+b=n-c\),所以 \(g\) 能整除 \(n-c\)。我们令 \(n-c=k\cdot g\)\(k=\frac {n-c}g\)。由于 \(g\)\(a,b\) 的最小公因数,\(\gcd(\frac a g,\frac b g)=1\)。由因为我们知道 \(\frac a g+\frac bg=k\),所以满足条件的 \(a,b\)\(\varphi(k)\) 对。

那么就做完了。

值得注意的是,在实现时我们可以枚举 \(g\)。因为枚举 \(c\) 的时间复杂度是 \(O(n\sqrt n)\)。而枚举 \(g\) 只需要 \(O(n\log n)\)

代码实现

//Don't act like a loser.
//This code is written by huayucaiji
//You can only use the code for studying or finding mistakes
//Or,you'll be punished by Sakyamuni!!!
#include<bits/stdc++.h>
#define int long long
using namespace std;

int read() {
	char ch=getchar();
	int f=1,x=0;
	while(ch<'0'||ch>'9') {
		if(ch=='-')
			f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		x=x*10+ch-'0';
		ch=getchar();
	}
	return f*x;
}
char read_char() {
	char ch=getchar();
	while(!isalpha(ch)) {
		ch=getchar();
	}
	return ch;
}

const int MAXN=1e5+10,MOD=1e9+7; 

int n,cnt;
int is[MAXN],p[MAXN],phi[MAXN];

int gcd(int a,int b) {
	return !b? a:gcd(b,a%b);
}
int lcm(int a,int b) {
	return a/gcd(a,b)*b;
}

void sieve(int n) {
	phi[1]=1;
	for(int i=2;i<=n;i++) {
		if(!is[i]) {
			p[++cnt]=i;
			phi[i]=i-1;
		}
		for(int j=1;j<=cnt&&p[j]*i<=n;j++) {
			is[p[j]*i]=1;
			if(i%p[j]==0) {
				phi[p[j]*i]=phi[i]*p[j]; 
				break;
			}
			phi[p[j]*i]=phi[i]*(p[j]-1);
		}
	}
}

signed main() {
	sieve(MAXN-10);
	cin>>n;
	int ans=0;
	for(int i=1;i<=n;i++) {
		for(int j=i*2;j<=n-1;j+=i) {
			ans=(ans+lcm(i,n-j)%MOD*phi[j/i]%MOD)%MOD;
		}
	}
	
	cout<<ans<<endl;
	
	return 0;
}

posted @ 2022-09-05 17:16  huayucaiji  阅读(44)  评论(0编辑  收藏  举报