题意很简单 求有多少组ab=cd
首先考虑 a=b=1时
对于每一个c和d都满足,所以一共是nn中
当a>1且b>1时
可以把a和c进行质因子分解,因为两边结果相等b和d只会改变每一个质因子的幂次,所以a和c所分解的质因子个数一定相同,把他们分解出来的质因子设为x1k1 和 x2k2(x1,x2为多个素数的乘积)所以说x1一定等于x2并且gcd(k1,k2)==1否则会出现重复的计数,所以只需要 xk1*a=xk2*b, 已知a,b,c,d的范围,k1,k2最大值也不会超过32(232>1e9)所以直接枚举k1,k2,然后根据数据范围可以得出对于不同的k1,k2有min(k1次根号n,k2次根号n)个x,然后需要k1a=k2*b,共有min(n/k1,n/k2)组a和b使得等式成立。
根据上述写完代码,wa98%绝活
ll ans=n*n%mod;
for(int i=1;i<=32;i++)
{
for(int j=1;j<=32;j++)
{
if(__gcd(i,j)==1)
{
ll x=pow(n,1.0/i);
ll y=pow(n,1.0/j);
ans=(ans+min(x-1,y-1)*min(n/i,n/j))%mod;
}
}
}
结果是精度问题,需要手动调精度,大概是pow开根号的时候产生的吧,大概吧!完结撒花
//手动调精度
while(qpow(x,i)<=n) x++;
while(qpow(y,j)<=n) y++;
x--,y--;
附代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7;
ll qpow(ll a, ll b)
{
ll ans = 1;
while(b){
if(b & 1) ans = (ans*a);
b>>=1;
a = (a*a);
}
return ans;
}
int main()
{
ll n;
while(cin>>n)
{
ll ans=n*n%mod;
for(int i=1;i<=32;i++)
{
for(int j=1;j<=32;j++)
{
if(__gcd(i,j)==1)
{
ll x=pow(n,1.0/i);
ll y=pow(n,1.0/j);
//手动调精度
while(qpow(x,i)<=n) x++;
while(qpow(y,j)<=n) y++;
x--,y--;
ans=(ans+min(x-1,y-1)*min(n/i,n/j))%mod;
}
}
}
cout<<ans<<endl;
}
}