Educational Codeforces Round 89 (Rated for Div. 2) D gcd拓展公式 卡longlong除法

题目

给你N个数
对于每个数Ai
问你能否给出一个答案,Ai是否存在两个因子d1 > 1 d2 > 1
满足
gcd(d1+d2,Ai) == 1
N <= 5e5

题解思路

引入一个定理
在这里插入图片描述
这题就很简单了,直接枚举比他小的质数,把这个质数拿从出去,除出另一边d2,然后判断是否为1即可。

d1肯定只有1个质数组成,而d2就由其他质数组成。

他们肯定是互质的,所以满足上面的式子。

这题在用质数试除的时候被卡longlong除了,建议少用longlong除。

AC代码

longlong乘

#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define ll long long

using namespace std;

const  int  INF =  0x3f3f3f3f;
const  int  N =  500100;
int d1[N] ;
int d2[N] ; 
int prm[N] ; 
int vis[N] ;
int a[N] ; 

int cnt ;  
void si()
{
    for (int i = 2 ; i <= N - 100 ; i++ )
    {
        if ( !vis[i] ) 
            prm[cnt] = i , cnt++ ;
        for (int j = 0 ; j < cnt && prm[j] <= (N-100)/i ; j++ )
        {
            vis[i*prm[j]] = 1 ;
            if ( i % prm[j] == 0 ) 
                    break ; 
        } 
    }
}
int main()
{
    //ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    si();
    int n ;
    scanf("%d",&n) ; 
    for (int i = 1 ; i <= n ; i++ )
        scanf("%d",&a[i]) ; 
    for (int i = 1 ; i <= n ; i++ )
    {
        long long  j ;
        j = a[i] ; 
        long long tt = 1 ; 
        int falg  = 0 ; 
        for (int k = 0 ; k < cnt && (long long )prm[k]*prm[k] <= j ; k++ )
        {
            while ( j % prm[k] == 0 )
            {
                j/=prm[k] ; 
                falg = 1 ; 
                tt*=prm[k] ; 
            }
            if ( falg )
                break ; 
        }
        if ( tt == 1 || j == 1 )
            d1[i] = -1 , d2[i] = -1 ;
        else
            d1[i] = tt , d2[i] = j ; 
    }
    for (int i = 1 ; i <= n ; i++ )
        cout << d1[i] << " " ;
    cout << "\n" ; 
    for (int i = 1 ; i <= n ; i++ )
        cout << d2[i] << " " ; 
    return 0 ;
}

int

#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define ll long long

using namespace std;

const  int  INF =  0x3f3f3f3f;
const  int  N =  500100;
int d1[N] ;
int d2[N] ; 
int prm[N] ; 
int vis[N] ;
int a[N] ; 

int cnt ;  
void si()
{
    for (int i = 2 ; i <= N - 100 ; i++ )
    {
        if ( !vis[i] ) 
            prm[cnt] = i , cnt++ ;
        for (int j = 0 ; j < cnt && prm[j] <= (N-100)/i ; j++ )
        {
            vis[i*prm[j]] = 1 ;
            if ( i % prm[j] == 0 ) 
                    break ; 
        } 
    }
}
int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    si();
    int n ;
    cin >> n ;
    for (int i = 1 ; i <= n ; i++ )
        cin >> a[i] ; 
    for (int i = 1 ; i <= n ; i++ )
    {
        int   j ;
        j = a[i] ; 
        int tt = 1 ; 
        int falg  = 0 ; 
        for (int k = 0 ; k < cnt && prm[k] <= j/prm[k] ; k++ )
        {
            while ( j % prm[k] == 0 )
            {
                j/=prm[k] ; 
                falg = 1 ; 
                tt*=prm[k] ; 
            }
            if ( falg )
                break ; 
        }
        if ( tt == 1 || j == 1 )
            d1[i] = -1 , d2[i] = -1 ;
        else
            d1[i] = tt , d2[i] = j ; 
    }
    for (int i = 1 ; i <= n ; i++ )
        cout << d1[i] << " " ;
    cout << "\n" ; 
    for (int i = 1 ; i <= n ; i++ )
        cout << d2[i] << " " ; 
    return 0 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值