Description
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 2, 3, 5, 7 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 = a, xk = 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
5 7
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;
}