【P1379】天才的约数和

时间:2023-03-10 00:36:21
【P1379】天才的约数和

来自GDOI2007,原题已不可考……

又自己做出来了好开心,找特殊性是个关键的切入点

原题:

这天周航遇到了靳泽旭。
   周航:“我是天才!”
   靳泽旭:“你为什么是天才?”
   周航:“你随便告诉我一个数字,我立即可以算出它所有约数之和,以及所有约数的倒数和!”
   靳泽旭:“换过来,我告诉你一个数的所有约数(包括1和该数本身)的和以及约数的倒数之和,你是天才你应该立即能推出这个数是什么!”
   周航被难倒了!
   现在,这个难倒了天才的题目就交到你手上了。

很像数论对吧

反正我没用数论知识

手玩小数据,玩到8的时候就可以发现一个很明显的规律:(不会搞表达式只能鼠绘一。一

【P1379】天才的约数和

把分母搞成一样的(通分)以后,分子就是所有约数和,分母是这个数,题目中也给出了约数和

分子上的约数和可能会和分母约掉,那么把分子和分母还原成约分之前的样子(分子分母同时*给出的约数和/分子)

如果给出的约数和%分子!=0,根据显然法可得,显然,无解

然后还需要验证一下,如果还原后的分母的约数和等于给出的约数和,还原后的分母就是答案

可以打表证明对于任意一组数据要么无解要么一组解,数学证明我不会(逃

在赛场上真不会也可以赌一下

然后搞一搞就行了,代码很好写

找特殊性是切入点,打表大法好

代码:

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
long long read(){long long z=,mark=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')mark=-; ch=getchar();}
while(ch>=''&&ch<=''){z=(z<<)+(z<<)+ch-''; ch=getchar();}
return z*mark;
}
long long a,b,c;
long long jie(long long x){
int _q=int(sqrt(x*1.0));
long long bowl=;
for(int i=;i<=_q;i++)if(!(x%i)) bowl+=i+x/i;
if(_q*_q==x) bowl-=_q;
return bowl;
}
int main(){//freopen("ddd.in","r",stdin);
for(;;){//徐王大法好
a=read(),b=read(),c=read();
if(!a && !b && !c) break;
if(a%b){ printf("0\n"); continue;}
c*=a/b;
if(a!=jie(c)) printf("0\n");
else printf("1 %lld\n",c);
}
return ;
}