题意:
将n-1(n为正整数)分为若干个n的约数倍数和(约数不为1或n).
n<=1e9.
无解输出"NO".
题解:
先考虑无解的情况,因为n-1与n互质,故若所有约数的公约数不为1,则n-1一定不能被表示,即n为一个质数的次幂时无解。
接着考虑剩余情况是否一定有解。
因为多个数过于复杂,故先考虑两个数。首先这两个数要互质,设n-1=ax+by(x,y|n,x,y为互质的大于1的正整数),于是只需证明存在正整数a,b满足等式即可。若n,x,y确定,则a,b为未知数,即可变形为b=(n-1-ax)/y,那么只需证明在a为正整数的时存在正整数b即可,即为:
1.y|(n-1-ax)
2.n-1-ax>0.
对于1, 由于y|n,故y|(ax+1),即ax=y-1(mod y)。显然由x,y互质得a取1~y-1中不同数时mod y下是不同的,于是必然存在a,使等式成立。
对于2,即ax<n-1,又a*x<=(y-1)x=xy-y<=n-y<n-1,故成立。
综上,有解。
那么构造就容易了,x,y取最小的两个不同的质因子即可。必然可以取一个小于sqrt(n)的y,然后在1~y-1内枚举判断,效率O(sqrt(n))。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
long long n;
long long gcd(long long a,long long b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
int main() {
while(~scanf("%lld",&n))
{
long long cur=1,cur1=1;
long long nn=n;
for(long long i=2;i*i<=n;i++)
{
if(n%i==0)
{
while(n%i==0)
{
n/=i;cur*=i;
}
}
if(cur>=nn/cur)
break;
cur1=cur;
}
cur=cur1;
if(cur==1 || cur==nn)
{
printf("NO\n");
} else
{
long long l=cur,r=nn/l;
long long l1,r1;
for(long long i=1;i<l;i++)
{
if((nn-1-i*r)%l==0)
{
r1=i;l1=(nn-1-i*r)/l;
break;
}
}
printf("YES\n");
printf("%d\n",2);
long long gcd1=gcd(l1,r);
printf("%lld %lld\n",l1/gcd1,r/gcd1);
long long gcd2=gcd(r1,l);
printf("%lld %lld\n",r1/gcd2,l/gcd2);
}
}
return 0;
}