CF1089F Fractions

题意:
将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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值