题意:
你只需要给出解的数量和所有解的 xyz 之和对 (109+7) 取模的值即可
若方程有无穷多组自然数解,则在这一行输出 “infty”(不含引号),否则在这一行输出两个整数,其中第一个整数表示方程的解数,第二个整数表示所有解的 xyz之和对 (109+7)取模的值,这两个整数之间用恰好一个空格隔开,行末不要有多余的空格。
解析:
是有理数的时候,只需要输出infty,因为只要保持y==z,就永远有解
那么其实答案最后可以化简成
n%4!=0 答案为 0 0
n%4==0
答案为 n/4的因子数/2 n/4的因子和*(n/4)
然后你可以对于每一个n暴力枚举因子,只要你写的常数够小,那么就可以过,我比赛的时候也是这么过的。
但是这道题是有一个更优的解法的,只需要153ms
就是质因数分解。
令m=n/4 ,m最大达到5e8,但是我们并不需要枚举那么多质数,只需要枚举以内的质数。
因为如果m里面最多只存在一个大于的质因子,因为如果存在两个,那么乘积就大于m了。
那么对于这一个大于质因子,当我们把m对
以内的质因子都分解了之后,
剩下了要么是1,要么就是那个大于的质因子。然后再进行判断处理就可以了。
要用质因数分解的原因是m的正因子和是一个积性函数
即,若a和b互质,那么f(ab)=f(a)f(b)
那么这样我们在质因数分解的时候,不同质因子之间,因子和直接相乘就可以了。
而同一个因子,只要求和就可以了(f(8)=f(2^3)=1+2+4+8)
最后不要忘了,如果剩下的是一个质数(>1),还要对他进行求一次答案。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1E5+10;
typedef long long ll;
const int MOD = 1e9+7;
int prime[N];
int main()
{
int t;
scanf("%d",&t);
int w=5e8;
int o;
int cnt=0;
for(int i=2;i*i<=w;i++){
int en=sqrt(i);
o=1;
for(int j=2;j<=en;j++)
if(i%j==0) {o=0;break;}
if(o) prime[cnt++]=i;
}
while(t--){
int n;
scanf("%d",&n);
int en=sqrt(n);
o=0;
for(int i=en-10;i<=en+10;i++)
if(i*i==n) {o=1;break;}
if(o)
{
printf("infty\n");
continue;
}
if(n%4)
{
printf("0 0\n");
continue;
}
n=n/4;
int x=1;
ll ans=n;
for(int i=0;i<cnt&&n>1;i++)
{
if(n%prime[i]==0){
int y=1;
o=1;
int j=1;
while(n%prime[i]==0)
{
j*=prime[i];
n/=prime[i];
o+=j;
//tm%=MOD;
y++;
}
x*=y;
ans*=o;
ans%=MOD;
}
}
if(n>1) //n是一个质数
{
ans*=(n+1);
x*=2;
}
ans%=MOD;
printf("%d %lld\n",x/2,ans);
}
}