题目描述
这天周航遇到了靳泽旭。
周航:“我是天才!”
靳泽旭:“你为什么是天才?”
周航:“你随便告诉我一个数字,我立即可以算出它所有约数之和,以及所有约数的倒数和!”
靳泽旭:“换过来,我告诉你一个数的所有约数(包括1和该数本身)的和以及约数的倒数之和,你是天才你应该立即能推出这个数是什么!”
周航被难倒了!
现在,这个难倒了天才的题目就交到你手上了。
输入格式
输入文件包含多组测试数据(最多有3000组测试数据)。每组测试数据有三个正整数A,B1和B2,(1<=A,B1,B2<=10^9),其中A为C的约数和,而对于C的所有倒数之和B,为避免精度误差,以分数B1/B2的形式给出。
输入文件以一行“0 0 0”结束。
输出格式
对于输入的每一组数据,输出一行。该行的第一个整数N是所有满足条件的不同的C的个数。其后按照从小到大的顺序输出N个数,为所有满足条件的C。相邻两个整数之间用空格隔开,行末不要有空格。
找不到题解,出处还是在百度快照里面找到的。
百度诚不可尽信之,它骗我说这个数是不唯一的,但实际上。……
设所求数为 n。
设约数之和为 a1+a2+a3…+an。
我们知道,对于每个约数 ai,都必然存在另一个唯一的约数 n / ai,也就是说,原式还可以表示成: a1+a2+a3…+an = n / a1 + n / a2 + n / a3…+ n / an = n*( 1 / a1 + 1 / a2 + 1 / a3…+ 1 / an )。
答案已经很显然了,amazing。
但是我们的数据不一定有合法解啊(显然有反例,比如 A=2,B1=1,B2=2)所以还要把求得的 n 求一遍约数和验证是否等于题目所给的 A 。求约数和有很多方法,可以暴力搞,我用了约数和的定理:
OJ上数据超出题面,爆了 int ,按道理说是不会的。合法的时候固然不会,不合法的时候验证所求的约数和就算溢出变成负数了,那也还是不合法的,完全不影响。
#include<bits/stdc++.h>
using namespace std;
long long a,b1_,b2_;
inline void read(long long &x)
{
x=0;int f=1;char s=getchar();
for(;s<'0'||s>'9';s=getchar()) if(s=='-') f=-1;
for(;s>='0'&&s<='9';s=getchar()) x=(x<<3)+(x<<1)+s-48;
}
inline long long check_(int x)
{
long long res=1;//约数和。
long long sum_,s;//s是每个质因子所属式子的和,sum_枚举每个质因子的含指数项。
for(int i=2;i*i<=x;++i)
if(!(x%i))
{
s=1LL;sum_=1LL;
for(;!(x%i);x/=i,sum_*=1LL*i,s+=sum_);
res*=s;
}
if(x!=1) res*=(x+1);
return res;
}
int main()
{
while(1)
{
read(a);read(b1_);read(b2_);
if(!a) return 0;
int n=a/b1_*b2_;
if(a%b1_||check_(n)!=1LL*a) printf("0\n");//不合法有两种情况,第一种是b1根本不能整除a,第二种是倒推的约数和与数据冲突。
else printf("1 %d\n",n);
}
return 0;
}
owo