2020 China Collegiate Programming Contest Weihai Site D ABC Conjecture(数论)

2020CCPC 威海站 D ABC Conjecture(数论)

题意 :给一个数 C(1-1e18),要求找到一个a,b。a+b=c;然后abc的积里面的素数因子要求< c,如果可以找到那么答案yes,否者no。

题解:首先可以明确的发现如果C是素数,一定是no,因为 a,b里面必然还有别的素因子,那么相乘必然大于c,所以现在就是判断合数,那么怎么样合数满足条件,C=A * B * C * D * E…;我们可以把C这样表示出来,然后要尽量去减少他的因数的贡献是不是他的因子里面就要有幂次的,这样子 他的贡献会产生到最小,然后a,b我们就根据素数因子来构造a+b=c;这样子一个可以使得贡献最小,列入 30 =5 * 2 * 3;我们无论怎么构造 a,b是不是都不可以减少贡献,因为C的贡献已经超过C本身了,那么如果是60=5 * 3 * 2 * 2;a=30,b=30;30=5 * 2 * 3; 最后的贡献是不是就变成30了,所以素数的枚举已经因子的幂次很重要 ,当大于2次幂的就会满足条件,最后我是枚举了1e7的素数,然后每次去判断是否有幂次的,如果1e7的素数找不到他的素数因子 ,那么该数必然是素数,或者素数因子大于1e7的范围,那么我们在前面处理的时候就先把他的素数单因子处理掉 ,最后在sqrt一下看看是不是能够开方,然后判断就好啦

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define fio ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mse(a,b) memset(a,b,sizeof a)
#define pb push_back
using namespace std;
const int mod=1e9+7;
const int maxx=1e7+10;
using namespace std;
const long double PI = 3.14159265358979323846;
//inline int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar(); } while (isdigit(ch)) { x=x*10+ch-48;  ch=getchar();  } return x*f;}
//     ll cc = ((1ll << 62) - 1 + (1ll << 62));
int vis[maxx];
int cnt=0;
int prime[maxx];
void pri()
{
    for(int i=2;i<=1e7;i++)
    {
        if(!vis[i]) prime[++cnt]=i;
        for(int j=1;j<=cnt&&prime[j]*i<1e7;j++)
        {
            vis[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
    }
}
signed main()
{
     pri();
    int t;
    cin>>t;
    while(t--){
       ll n;
       cin>>n;
       bool flag=false;
       for(int i=1;i<=cnt&&n>=i*i;i++)
       {
           if(n%(prime[i]*prime[i])==0)
           {
               flag=true;
               break;
           }
           if(n%prime[i]==0)
            n/=prime[i];
       }
       if(flag) cout<<"yes"<<endl;
       else if(n>1){
            ll ans=sqrt(n);
            if(ans*ans==n) cout<<"yes"<<endl;
            else cout<<"no"<<endl;
       }
       else cout<<"no"<<endl;
    }
    return 0;

}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值