Goldbach

Goldbach

2018 ACM-ICPC 中国大学生程序设计竞赛…
就是哥德巴赫猜想。就是数值特别大!!一直没过,最后几分钟把long lon改成了unsigned long long就过了!
此处贴一个(模板)米勒罗宾素数测试;

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<cstring>
#include<iostream>
using namespace std;
typedef unsigned long long LL;
const LL maxn=10000;
LL my_prime[maxn];
int k=0;
bool vis[maxn*10]={0};
void pri(){

    vis[0]=1;
    vis[1]=1;
    for(LL i=2;i<maxn*10;i++)
    {
        if(!vis[i])
        {
            vis[i]=1;
            my_prime[k++]=i;
            for(LL j=i+i;j<maxn*10;j+=i)
            vis[j]=1;
        }
    } 
}

bool isPrime_3(LL num )
{
    if(num ==2|| num==3 )
    return 1 ;
    if( num%6!= 1&&num %6!= 5)
    return 0 ;
    LL tmp =sqrt( num);
     for(LL i= 5;i <=tmp; i+=6 )
     if(num %i== 0||num %(i+ 2)==0 )
     return 0 ;
     return 1 ;
}

LL prime[6] = {2, 3, 5, 233, 331};
LL qmul(LL x, LL y, LL mod) { // 乘法防止溢出, 如果p * p不爆LL的话可以直接乘; O(1)乘法或者转化成二进制加法

    return (x * y - (long long)(x / (long double)mod * y + 1e-3) *mod + mod) % mod;
}
LL qpow(LL a, LL n, LL mod) {
    LL ret = 1;
    while(n) {
        if(n & 1) ret = qmul(ret, a, mod);
        a = qmul(a, a, mod);
        n >>= 1;
    }
    return ret;
}
bool Miller_Rabin(LL p) {
    if(p < 2) return 0;
    if(p != 2 && p % 2 == 0) return 0;
    LL s = p - 1;
    while(! (s & 1)) s>>=1;
    for(int i = 0; i < 5; ++i) {
        if(p == prime[i]) return 1;
        LL t = s, m = qpow(prime[i], s, p);
        while(t != p - 1 && m != 1 && m != p - 1) {
            m = qmul(m, m, p);
            t <<= 1;
        }
        if(m != p - 1 && !(t & 1)) return 0;
    }
    return 1;
}
int main()
{
    pri();
    LL n;
    LL a;
    scanf("%lld",&n);
    while(n--)
    {

        scanf("%lld",&a);
        LL i=0,flag=0;
        LL t; 
        if(a<100)
        {
            for(i=0;i<k;i++)
            {
                t=a-my_prime[i];
                if(t>3&&t%3==0) continue;
                if(t>5&&t%5==0) continue;
                if(t>7&&t%7==0) continue;
                if(t>11&&t%11==0) continue;
                if(isPrime_3(t))
                {
                    flag=1;
                    break;
                }
            }
        }
        else
        {
            for(i=0;i<k;i++)
            {
                t=a-my_prime[i];
                if(t>3&&t%3==0) continue;
                if(t>5&&t%5==0) continue;
                if(t>7&&t%7==0) continue;
                if(t>11&&t%11==0) continue;
                if(Miller_Rabin(t))
                {
                    flag=1;
                    break;
                }
            }
        }
        if(flag)
        printf("%lld %lld\n",my_prime[i],t);
        else
        {
            LL q=my_prime[k-1],p;
            while(!flag)
            {
                q+=2;
                if(!Miller_Rabin(q))continue;
                p=a-q;
                if(!Miller_Rabin(p))continue;
                flag=1;
                break;
            }
            printf("%lld %lld\n",q,p);
        }

    }
    return 0;
}
//9223372036854775807
//1844674407370955161

(模板)

LL prime[6] = {2, 3, 5, 233, 331};
LL qmul(LL x, LL y, LL mod) { // 乘法防止溢出, 如果p * p不爆LL的话可以直接乘; O(1)乘法或者转化成二进制加法

    return (x * y - (long long)(x / (long double)mod * y + 1e-3) *mod + mod) % mod;
}
LL qpow(LL a, LL n, LL mod) {
    LL ret = 1;
    while(n) {
        if(n & 1) ret = qmul(ret, a, mod);
        a = qmul(a, a, mod);
        n >>= 1;
    }
    return ret;
}
bool Miller_Rabin(LL p) {
    if(p < 2) return 0;
    if(p != 2 && p % 2 == 0) return 0;
    LL s = p - 1;
    while(! (s & 1)) s>>=1;
    for(int i = 0; i < 5; ++i) {
        if(p == prime[i]) return 1;
        LL t = s, m = qpow(prime[i], s, p);
        while(t != p - 1 && m != 1 && m != p - 1) {
            m = qmul(m, m, p);
            t <<= 1;
        }
        if(m != p - 1 && !(t & 1)) return 0;
    }
    return 1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值