Gym 101138I Prime Moving【素数测试】

11 篇文章 0 订阅
10 篇文章 0 订阅

Description

standard input/output
Statements

The author of this problem hopes that you already know the pig called Benny.

Recently she started learning numbers. The first type of numbers she has learnt are primes, i.e. positive integers with

 exactly two divisors. First few primes are 2357 and 11. As a homework Benny was given two primes a and b.

 She has to transform a into b using addition and subtraction.Since Benny knows only primes, she might add and

 subtract only primes. Moreover, all the partial results also have to be primes.One move is either adding or

 subtracting a prime to/from the current number. A way of transforming a into bis called optimal if it doesn't 

use more moves than any other way. Your task is to find the only optimal way, if exactly one exists.

If it's impossible to transform a into b, print "Unlucky Benny" (without the quotes). If there are multiple

 optimal ways, print "Poor Benny" (without the quotes). Otherwise output the transformation with all 

partial results. See the output format below.

Input

The only line of the input contains two integers a and b (2 ≤ a < b ≤ 1015). Both a and b are primes.

Output

If the transformation is impossible, print "Unlucky Benny".

If there are many optimal ways, print "Poor Benny".

If there is exactly one optimal way to transform a into b, describe the process in the following format.

 Letx1, x2, ..., xk denote values of Benny's number in the order. So x1 = axk = b and Benny 

changes xi to xi + 1in the i-th move. In a single line print k numbers separated with two 

characters "->", without the quotes and spaces.

Sample Input

Input
5 7
Output
5->7

Hint

One move is enough in the sample.

If the only optimal way was to change 5 to 20, then change 20 to 10, and then finally change 10 to 7,

 the output would be 5->20->10->7. Though, such a way is not only non-optimal but also it isn't valid.

 In the first move (from 5 to 20) we try to add 15 what 

is not prime. Also, a new number 20 isn't prime. This note is only to show you the correct format.



/*
    题意:给你两个素数a,b,要你仅通过加法或减法只使用素数进行运算从a得到b
          如果不存在方案输出"Unlucky Benny",如果存在多条最优的方案输出
          "Poor Benny",否则输出方案路径
    类型:素数测试+脑洞
    分析:因为a,b的范围在10^15以内,所以要用素数测试算法,这部分可以套模版
          然后就是怎么做的问题.首先列举一下素数出来看看
          2 3 5 7 11 13 17 19...
          分两种情况讨论:
          第一种:a=2时,这时候先看b-2是否为素数,如果是的话我们可以a+b-2得到b
                 所以路径是2->b;如果b-2不是素数,再看b+2是不是素数,如果是的话,
                 我们可以a+(b+2)-2得到b即2->b+2->b,如果b+2不是素数则无解,因为
                 不可能存在a+素数k+素数k'+..=b的情况,why?因为素数k+素数k'就不是
                 素数了(除了2以外,其他素数都是奇数,两个奇数相加=偶数能被2整除)
          第二种:a!=2时,首先可以确定的是a+2/-2这样的方式移动,原因上面说过了,并且
                 这里向一个方向移动的次数<2也就是+2/-2在一个方向是最多进行一次,
                 why?因为进行两次相当于a+4/-4而4不是素数.
                 所以一共有这么几种情况:
                 a+2=b;(例如5->7)
                 a-(a-2)=2,回到情况一找b;(例如5->2->13)
                 a+2-(a-2)=2,回到情况一找b;(例如3->5->2->13)
          最复杂的情况长度为5,例如3->5->2->1000000009->1000000007
          另外这道题不存在在最优的情况下有多解,因为最优是讨论-2,再讨论+2,只有一条最
          优的路
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const long long S=20;
long long mult_mod(long long a,long long b,long long c){
    a%=c;
    b%=c;
    long long ret=0;
    while(b){
        if(b&1){ret+=a;ret%=c;}
        a<<=1;
        if(a>=c)a%=c;
        b>>=1;
    }
    return ret;
}
long long pow_mod(long long x,long long n,long long mod){
    if(n==1)return x%mod;
    x%=mod;
    long long tmp=x;
    long long ret=1;
    while(n){
        if(n&1) ret=mult_mod(ret,tmp,mod);
        tmp=mult_mod(tmp,tmp,mod);
        n>>=1;
    }
    return ret;
}
bool check(long long a,long long n,long long x,long long t){
    long long ret=pow_mod(a,x,n);
    long long last=ret;
    for(long long i=1;i<=t;i++){
        ret=mult_mod(ret,ret,n);
        if(ret==1&&last!=1&&last!=n-1) return true;
        last=ret;
    }
    if(ret!=1) return true;
    return false;
}
bool Miller_Rabin(long long n){
    if(n<2)return false;
    if(n==2)return true;
    if((n&1)==0) return false;
    long long x=n-1;
    long long t=0;
    while((x&1)==0){x>>=1;t++;}
    for(long long  i=0;i<S;i++){
        long long a=rand()%(n-1)+1;
        if(check(a,n,x,t))
            return false;
    }
    return true;
}
long long factor[1000000];
long long tol;
long long gcd(long long a,long long b){
    if(a==0)return 1;
    if(a<0)return gcd(-a,b);
    while(b){
        long long t=a%b;
        a=b;
        b=t;
    }
    return a;
}
long long Pollard_rho(long long x,long long c){
    long long i=1,k=2;
    long long x0=rand()%x;
    long long y=x0;
    while(1){
        i++;
        x0=(mult_mod(x0,x0,x)+c)%x;
        long long d=gcd(y-x0,x);
        if(d!=1&&d!=x) return d;
        if(y==x0) return x;
        if(i==k){y=x0;k+=k;}
    }
}
void findfac(long long n){
    if(Miller_Rabin(n)){
        factor[tol++]=n;
        return;
    }
    long long p=n;
    while(p>=n)p=Pollard_rho(p,rand()%(n-1)+1);
    findfac(p);
    findfac(n/p);
}
vector<long long>v;
void print(){
    long long len=v.size();
    printf("%I64d",v[0]);
    for(long long  i=1;i<len;i++){
        printf("->%I64d",v[i]);
    }puts("");
}
int main(){
    long long a,b;
    while(scanf("%I64d%I64d",&a,&b)!=EOF){
        if(a==2){
            if(Miller_Rabin(b-2)){
                printf("%I64d->%I64d\n",a,b);
                continue;
            }
            if(Miller_Rabin(b+2))printf("%I64d->%I64d->%I64d\n",a,b+2,b);
            else printf("Unlucky Benny\n");
        }
        else{
            v.clear();v.push_back(a);
            long long t=a;
            while(t<b){
                t+=2;
                if(Miller_Rabin(t)){
                    v.push_back(t);
                    if(t==b)print();
                }
                else{
                    v.clear();v.push_back(a);
                    if(Miller_Rabin(a-2)){
                        v.push_back(2);
                        if(Miller_Rabin(b-2)){
                            v.push_back(b);
                            print();
                            break;
                        }
                        if(Miller_Rabin(b+2)){
                            v.push_back(b+2);v.push_back(b);
                            print();
                            break;
                        }
                    }
                    if(Miller_Rabin(a+2)){
                        v.push_back(a+2);a+=2;
                        if(Miller_Rabin(a-2)){
                            v.push_back(2);
                            if(Miller_Rabin(b-2)){
                                v.push_back(b);
                                print();
                                break;
                            }
                            if(Miller_Rabin(b+2)){
                                v.push_back(b+2);v.push_back(b);
                                print();
                                break;
                            }
                        }
                    }
                    printf("Unlucky Benny\n");
                    break;
                }
            }
        }
    }
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值