题目链接
Problem Description
Goffi is doing his math homework and he finds an equality on his text book: gcd(n−a,n)×gcd(n−b,n)=nk.
Goffi wants to know the number of (a,b) satisfy the equality, if n and k are given and 1≤a,b≤n.
Note: gcd(a,b) means greatest common divisor of a and b.
Input
Input contains multiple test cases (less than 100). For each test case, there’s one line containing two integers n and k (1≤n,k≤109).
Output
For each test case, output a single integer indicating the number of (a,b) modulo 109+7.
Sample Input
2 1
3 2
Sample Output
2
1
Hint
For the first case, (2, 1) and (1, 2) satisfy the equality.
思路:一开始看到这个式子被吓到了,其实就是长得吓人,仔细思考一下。首先等式的两个gcd最大值肯定不超过n,所以n大于2的直接为0,n等于2的时候只有一种可能就是两个都为n(因为你想想两个数相乘要为n^2,两个都比n小的数是不可能成为n平方的,所以只有nn),剩下的就是k等于1的时候了,这时候又体现了欧拉的神奇之处了,我们设gcd(n-a,n)为x,那么等于是不是就等于gcd(n-a/x,n/x)要想找到满足条件的a的话答案就是就是枚举n的因子求它的欧拉函数(由于并没有要我们求出具体a和b,只要求个数就行了,那么直接欧拉函数就行了),gcd(n-b,n)也是同理,根据乘法原理,答案为两边相乘再乘2,只要注意一下ii==n的时候两边会重复计算,特判一下就行。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll get_euler(ll n){
ll res=n,a=n;
for (ll i = 2; i*i<=a;i++){
if(a%i==0){
res=res/i*(i-1);
while(a%i==0) a=a/i;
}
}
if(a>1) res=res/a*(a-1);
return res;
}
int main()
{
ll n,k;
while(scanf("%lld %lld",&n,&k)!=EOF)
{
ll ans=0;
if(n==1){
printf("1\n");continue;
}
if(k>2) {
printf("0\n");continue;
}
if(k==2){
printf("1\n");continue;
}
if(k==1){
for(ll i=1;i*i<=n;++i)
{
if(n%i==0)
{
if(i*i==n) ans+=get_euler(n/i)*get_euler(i);
else ans+=2*get_euler(n/i)*get_euler(i);
ans%=mod;
}
}
}
printf("%lld\n",ans);
}
}