1. 程式人生 > >上海五校賽 密碼破解

上海五校賽 密碼破解

queue ios 上海 fin problem 無法 label 對稱 div

密碼破解

發布時間: 2017年7月9日 18:17 最後更新: 2017年7月9日 21:04 時間限制: 1000ms 內存限制: 128M

近日來勒索病毒的事件頻繁發生,小Y對它的加密原理非常感興趣,研究了一番相關知識之後,他就來給你看他的加密程序,並給你一段密文,和你炫耀說就算把程序給你看你也破解不出來。

你掃了一眼代碼發現加密的公式為b=a e %m ,其中e 是質數。

進一步分析發現m=pq p q 都為質數,p!=q

作為一個計算機高手,你早就對加密算法爛熟於心,一眼就看出這個程序的算法和原理,找到了破解的方法,發現小Y疏忽在與給了你一個不夠大的m

你知道解密的公式與加密對稱,為a=b d %m

但是你仍然無法心算解出這個d ,因此你需要借助計算機來將密文破解。

第一行有一個整數T 表示數據組數。(T<=100
接著有T 組數據,每組數據兩行。
第一行有四個數e p q n ,其中e p q 如題所描述,n 表示需要解密的數字序列長度。
第二行是需要解密的數字序列a 1 ..a n
1 < p ,q ,e <= 10 8 p q

e 為質數且p!=q
$0<=a_i<m$。($1<=i<=n$)< br=""> 保證解密的結果即原數列的值小於min(p,q) 並大於等於0
1<=n<=100
保證m 有且僅有兩個不同的質因數p q ,並且一定存在一個題中描述的參數d 使得解密公式能夠無損解密出所有0 ~min(p,q)1 範圍之間的數字。

對於每組數據輸出一行,表示解密後的數字序列,數字之間以空格隔開。

復制
1
5 19 29 3
335 440 514
65 67 77
分析:首先有個性質,(d*e)=1(mod Φm);
   然後就簡單了,求出Φm = (p-1)*(q-1),利用擴歐解出d,最後快速冪即可;
   註意坑點是乘法可能爆long long;
代碼:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <bitset>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#include <cassert>
#include <ctime>
#define rep(i,m,n) for(i=m;i<=(int)n;i++)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define vi vector<int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define pi acos(-1.0)
#define pii pair<int,int>
#define sys system("pause")
#define ls rt<<1
#define rs rt<<1|1
const int maxn=1e3+10;
const int N=5e2+10;
using namespace std;
ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
ll qmul(ll p,ll q,ll mo){ll f=0;while(q){if(q&1)f=(f+p)%mo;p=(p+p)%mo;q>>=1;}return f;}
ll qpow(ll p,ll q,ll mo){ll f=1;while(q){if(q&1)f=qmul(f,p,mo)%mo;p=qmul(p,p,mo)%mo;q>>=1;}return f;}
int n,m,k,t;
ll a[maxn],ret[maxn];
ll e_gcd(ll a,ll b,ll &x,ll &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    ll ans=e_gcd(b,a%b,x,y);
    ll temp=x;
    x=y;
    y=temp-a/b*y;
    return ans;
}

ll cal(ll a,ll b,ll c)
{
    ll x,y;
    ll gcd=e_gcd(a,b,x,y);
    if(c%gcd!=0) return -1;
    x*=c/gcd;
    b/=gcd;
    if(b<0) b=-b;
    ll ans=x%b;
    if(ans<=0) ans+=b;
    return ans;
}
int main()
{
    int i,j;
    scanf("%d",&t);
    while(t--)
    {
        int e;
        ll p,q;
        scanf("%d%lld%lld%d",&e,&p,&q,&n);
        rep(i,1,n)scanf("%lld",&a[i]);
        ll d=cal(e,(p-1)*(q-1),1);
        rep(i,1,n)ret[i]=qpow(a[i],d,p*q);
        rep(i,1,n)printf("%lld%c",ret[i],i==n?\n: );
    }
    return 0;
}

上海五校賽 密碼破解