hdu 4983 Goffi and GCD(欧拉函数)

时间:2022-07-30 02:39:19

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
 
 
Sample Output

Hint

For the first case, (2, 1) and (1, 2) satisfy the equality.

 
Source
 发现自己欧拉函数都给忘记了,所有赶紧补题。。。
1、k!=1时情况很简单,记住将if(k==2 || n==1)这个特判放在if(k>2)的前面,因为这个WA了很久,各种原因自己思考。
2、下面讨论k=1时情况。x=gcd(n-a,n),则n/x=gcd(n-b,n),因为n-a可以取到0...n-1也就是1....n,所以完全可以去掉n-这个限制条件,即gcd(a,n)=x、gcd(b,n)=n/x时个数,因为a<=n,所以gcd(a,n)的个数=u[n/x],u是欧拉函数。所以原式等于sigma(u[n/x]*u[x])其中x是n的约数。
 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MOD 1000000007
#define ll long long
ll eular(ll n)
{
ll res=;
for(ll i=;i*i<=n;i++)
{
if(n%i==)
{
n/=i,res*=i-;
while(n%i==)
{
n/=i;
res*=i;
}
}
}
if(n>) res*=n-;
return res;
}
ll n,k;
int main()
{
while(scanf("%I64d%I64d",&n,&k)==)
{
if(k== || n==)
{
printf("1\n");
continue;
}
if(k>)
{
printf("0\n");
continue;
} ll ans=;
for(ll i=;i*i<=n;i++)
{
if(n%i==)
{
if(i*i!=n)
ans=(ans+eular(n/i)*eular(i)*)%MOD;
else
ans=(ans+eular(n/i)*eular(i))%MOD;
}
}
printf("%I64d\n",ans); }
return ;
}