Decrypt Messages
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 554 Accepted Submission(s): 135
Problem Description
In the game BioHazard 4, the president's daughter has been abducted by some crazy villagers. Leon S. Kennedy, the secret agent of White House, goes to rescue her. He keeps in contact with Hunnigan, the president's secretary.
But the time in their contact log has been encrypted, using the following method:
Count the number of seconds from 2000.01.01 00:00:00 to that time, assume this number is x. Then calculate xq, modulo it by a prime number p. The remainder a is the encrypted number.
Your task is to help Leon write a program to decrypt the contact log, and tell him all the possible original time.
1. Remember that if the year can be divided evenly by 4 but can't be divided evenly by 100, or it can be divided evenly by 400, this year is a leap year. The February of a leap year has 29 days, while the February of other years has 28 days.
2. In this problem, if the year modulo 10 is 5 or 8, at the end of this year, there is one “leap second”, i.e., the second after 2005.12.31 23:59:59 is 2005.12.31 23:59:60, and after that second, it's 2006.01.01 00:00:00.
You may assume that from 2000.01.01 00:00:00 till that time, less than p seconds have passed.
But the time in their contact log has been encrypted, using the following method:
Count the number of seconds from 2000.01.01 00:00:00 to that time, assume this number is x. Then calculate xq, modulo it by a prime number p. The remainder a is the encrypted number.
Your task is to help Leon write a program to decrypt the contact log, and tell him all the possible original time.
1. Remember that if the year can be divided evenly by 4 but can't be divided evenly by 100, or it can be divided evenly by 400, this year is a leap year. The February of a leap year has 29 days, while the February of other years has 28 days.
2. In this problem, if the year modulo 10 is 5 or 8, at the end of this year, there is one “leap second”, i.e., the second after 2005.12.31 23:59:59 is 2005.12.31 23:59:60, and after that second, it's 2006.01.01 00:00:00.
You may assume that from 2000.01.01 00:00:00 till that time, less than p seconds have passed.
Input
There are multiple test cases.
The first line of the input contains an integer T, meaning the number of the test cases.
For each test case, a single line of three integers: p, q, and a. (2<p≤1000000007, 1<q≤10, 0≤a<p, p is always a prime.)
The first line of the input contains an integer T, meaning the number of the test cases.
For each test case, a single line of three integers: p, q, and a. (2<p≤1000000007, 1<q≤10, 0≤a<p, p is always a prime.)
Output
The time. If there are multiple solutions, you must output all possible solutions in chronological order.
If the solution doesn't exist, output Transmission error instead.
See the sample output for further details.
If the solution doesn't exist, output Transmission error instead.
See the sample output for further details.
Sample Input
2 3 2 1 3 2 2
Sample Output
Case #1: 2000.01.01 00:00:01 2000.01.01 00:00:02 Case #2: Transmission error
Source
- N次剩余:
x^q = a (mod p);- 因为数据量的关系,解出方程的解之后逐年计算秒即可
- 题目里面除了leap year的概念外,还添加有leap second的概念,要引起高度重视
- 对于leap year不用多说
- 对于leap second的话,记得在处理 year,month,day的时候都要加以考虑
- 在整年整月以及跨年日的特殊节点要加上 leap second
- 而且在处理完成后
- 在最后要考虑特殊情况,即跨年日最后一秒后如果是 leap second
- 当时的 小时是24h,要将时间调成 23:59:60(血坑~)
#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
typedef long long LL ;
typedef unsigned long long ULL ;
const int maxn = 1000 + 10 ;
const int inf = 0x3f3f3f3f ;
const int npos = -1 ;
const int mod = 1e9 + 7 ;
const int mxx = 100 + 5 ;
const double eps = 1e-6 ;
const LL second = 1 ;
const LL minute = 60 ;
const LL hour = 3600 ;
const LL day = 86400 ;
#define m(x) (x*day) ;
const LL Uyear = 365*day ;
const LL Lyear = 366*day ;
LL isleap_y(LL x){
return !(x%400) || (!(x%4) && x%100);
}
LL isleap_s(LL x){
return (5==(x%10)) || (8==(x%10));
}
LL extgcd(LL a, LL b, LL &x, LL &y){
if(0==b){
x=1;
y=0;
return a;
}else{
int r=extgcd(b,a%b,y,x);
y-=x*(a/b);
return r;
}
}
LL pow_mod(LL x, LL k, LL m){
LL r=1%m;
while(k){
if(1&k)r=((r*x)%m + m)%m;
x=((x*x)%m + m)%m;
k>>=1;
}
return r;
}
int g_test(LL g, LL p, vector<LL> &v){
LL sz=v.size();
for(LL i=0;i<sz;i++)
if(1==pow_mod(g,(p-1)/v[i],p))
return 0;
return 1;
}
LL primitive_rt(LL p){
LL t=p-1;
std::vector<LL> v;
for(LL i=2;i<=t/i;i++)
if(0==t%i){
v.push_back(i);
while(0==t%i)
t/=i;
}
if(1!=t)
v.push_back(t);
LL g=1;
while(true){
if(g_test(g,p,v))
return g;
g++;
}
}
LL discrete_log(LL x, LL n, LL m){
// x^y = n (mod m)
map< LL, LL > rec;
LL s=(LL)sqrt((double)m);
while(s*s<=m)s++;
LL cur=1;
for(LL i=0;i<s;i++){
rec[cur]=i;
cur=((cur*x)%m + m)%m;
}
LL mul=cur;
cur=1;
for(LL i=0;i<s;i++){
LL more=(n*pow_mod(cur,m-2,m)%m + m)%m;
if(rec.count(more))
return i*s + rec[more];
cur=((cur*mul)%m + m)%m;
}
return -1;
}
vector<LL> n_residue(LL N, LL a, LL p){
// x^N = a (mod p)
vector<LL> res;
LL g=primitive_rt(p);
LL m=discrete_log(g,a,p);
if(0==a){
res.push_back(0);
return res;
}
if(-1==m){
return res;
}
LL A=N, B=p-1, C=m, x, y;
LL d=extgcd(A,B,x,y);
if(0 != C%d){
return res;
}
x=x*(C/d)%B;
LL delta=B/d;
for(LL i=0;i<d;i++){
x=((x+delta)%B + B)%B;
res.push_back(pow_mod(g,x,p));
}
sort(res.begin(),res.end());
res.erase(unique(res.begin(),res.end()),res.end());
return res;
}
// 1 3 5 7 8 10 12
LL mo[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
void show(LL x, LL y, LL m, LL d, LL hh, LL mm, LL ss){
LL yt, mt, dt, hht, mmt, sst;
while(x){// year
if(isleap_y(y)){
mo[2]=(LL)29; yt=Lyear;
}else{
mo[2]=(LL)28; yt=Uyear;
}
yt+=isleap_s(y);
if(x>=yt){
y++; x-=yt; continue;
}
while(x){// month
mt=m(mo[m]);
mt+=(isleap_s(y) && 12==m);
if(x>=mt){
m++; x-=mt; continue;
}
while(x){// day
dt=day;
dt+=(isleap_s(y) && 12==m && 31==d);
if(x>=dt){
d++; x-=dt; continue;
}
if(x){hh+=x/hour; x%=hour; }// hour
if(x){mm+=x/minute; x%=minute;}// minute
if(x){ss+=x/second; x%=second;}// second
}
}
}
if(24==hh){
hh=23; mm=59; ss=60;
}
printf("%4lld.%02lld.%02lld %02lld:%02lld:%02lld\n",
y,m,d,hh,mm,ss);
}
int T, kase;
LL p, q, a, y =2000, m =1, d =1, hh=0, mm=0, ss=0;
vector<LL> ans;
int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
while(~scanf("%d",&T)){
for(kase=1;kase<=T;kase++){
scanf("%lld %lld %lld",&p,&q,&a);
ans=n_residue(q,a,p);
printf("Case #%d:\n",kase);
if(ans.size())
for(int i=0, sz=ans.size();i<sz;i++)
show(ans[i],y,m,d,hh,mm,ss);
else
printf("Transmission error\n");
}
}
return 0;
}
本文介绍了一个基于特定加密方法的游戏时间记录解密问题,通过数学运算还原加密的时间记录,包括了解决方案的算法实现细节。
553

被折叠的 条评论
为什么被折叠?



