题意:输入正整数$K_1(K_1 \leq 50000)$, 找一个$12$位正整数$K_2$(不能含有前导零)使得${K_1}^{K_2}\equiv K_2(mod10^{12})$。

例如,$K_1=78$和$99$时,$K_2$分别为$308646916096$和$817245479899$。

分析:这题还是需要搜索来寻找答案的,直接构造很困难。事实上,${K_1}^{K_2}\equiv K_2(mod10^{12})$,同时意味着:

${K_1}^{K_2}\equiv K_2(mod10^{i}), i \leq 12$。

并且有$\varphi(10^i)={10^i}(1-\frac{1}{2})(1-\frac{1}{5})=4\cdot10^{i-1}$

于是${K_1}^{K_2}\mod {10^i}={K_1}^{K_2\mod{\varphi(10^i)}+\varphi(10^i)}\mod {10^i}$

于是${K_1}^{K_2}\mod {10^i}={K_1}^{K_3}\mod {10^i}\iff\varphi(10^i) | (K_3 - K_2)$

满足上式的一个充分条件是$10^{i+1} | (K_3 - K_2)$

也就是说,我们从低到高枚举$K_2$第$i$位的值,同时枚举其第$i+1$位的值,那么只要从最低位到第$i+1$位关于分解后对应模方程是合法的,

在以后的构造过程中始终不会破坏当前的性质,因为高位的那些值对当前模取模值都是相同的。

那么我们就可以边枚举边验证进行dfs了。

交了之后发现TLE了。为了保证快速幂时乘法不溢出,又用了一个快速乘法操作,这个操作实际上是可以从$O(log(n))$优化到$O(1)$的。

首先考虑模数最大为$10^{12}$,不超过$2$进制中的$40$位,那么我们可以将待乘值拆分成高$20$位与低$20$位,确保在乘法时始终不超过$60$位,

用long long就不会溢出,具体如下:

$a\cdot b \mod n = a \cdot ((b>>20)\cdot(1<<20) + b \& ((1 <<20) - 1)\mod n$

$= ((a\cdot(b>>20)\mod n)\cdot(1<<20)\mod n) + (a\cdot(b \& ((1 <<20) - 1))))\mod n$

这样优化之后就可以通过了。

 #include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <iostream>
#include <assert.h>
#define PI acos(-1.)
#pragma comment(linker, "/STACK:102400000,102400000")
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define mp make_pair
#define st first
#define nd second
#define keyn (root->ch[1]->ch[0])
#define lson (u << 1)
#define rson (u << 1 | 1)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define type(x) __typeof(x.begin())
#define foreach(i, j) for(type(j)i = j.begin(); i != j.end(); i++)
#define FOR(i, s, t) for(int i = (s); i <= (t); i++)
#define ROF(i, t, s) for(int i = (t); i >= (s); i--)
#define dbg(x) cout << x << endl
#define dbg2(x, y) cout << x << " " << y << endl
#define clr(x, i) memset(x, (i), sizeof(x))
#define maximize(x, y) x = max((x), (y))
#define minimize(x, y) x = min((x), (y))
using namespace std;
typedef long long ll;
const int int_inf = 0x3f3f3f3f;
const ll ll_inf = 0x3f3f3f3f3f3f3f3f;
const int INT_INF = (int)((1ll << ) - );
const double double_inf = 1e30;
const double eps = 1e-;
typedef unsigned long long ul;
inline int readint(){
int x;
scanf("%d", &x);
return x;
}
inline int readstr(char *s){
scanf("%s", s);
return strlen(s);
}
//Here goes 2d geometry templates
struct Point{
double x, y;
Point(double x = , double y = ) : x(x), y(y) {}
};
typedef Point Vector;
Vector operator + (Vector A, Vector B){
return Vector(A.x + B.x, A.y + B.y);
}
Vector operator - (Point A, Point B){
return Vector(A.x - B.x, A.y - B.y);
}
Vector operator * (Vector A, double p){
return Vector(A.x * p, A.y * p);
}
Vector operator / (Vector A, double p){
return Vector(A.x / p, A.y / p);
}
bool operator < (const Point& a, const Point& b){
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
int dcmp(double x){
if(abs(x) < eps) return ;
return x < ? - : ;
}
bool operator == (const Point& a, const Point& b){
return dcmp(a.x - b.x) == && dcmp(a.y - b.y) == ;
}
double Dot(Vector A, Vector B){
return A.x * B.x + A.y * B.y;
}
double Len(Vector A){
return sqrt(Dot(A, A));
}
double Angle(Vector A, Vector B){
return acos(Dot(A, B) / Len(A) / Len(B));
}
double Cross(Vector A, Vector B){
return A.x * B.y - A.y * B.x;
}
double Area2(Point A, Point B, Point C){
return Cross(B - A, C - A);
}
Vector Rotate(Vector A, double rad){
//rotate counterclockwise
return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad));
}
Vector Normal(Vector A){
double L = Len(A);
return Vector(-A.y / L, A.x / L);
}
void Normallize(Vector &A){
double L = Len(A);
A.x /= L, A.y /= L;
}
Point GetLineIntersection(Point P, Vector v, Point Q, Vector w){
Vector u = P - Q;
double t = Cross(w, u) / Cross(v, w);
return P + v * t;
}
double DistanceToLine(Point P, Point A, Point B){
Vector v1 = B - A, v2 = P - A;
return abs(Cross(v1, v2)) / Len(v1);
}
double DistanceToSegment(Point P, Point A, Point B){
if(A == B) return Len(P - A);
Vector v1 = B - A, v2 = P - A, v3 = P - B;
if(dcmp(Dot(v1, v2)) < ) return Len(v2);
else if(dcmp(Dot(v1, v3)) > ) return Len(v3);
else return abs(Cross(v1, v2)) / Len(v1);
}
Point GetLineProjection(Point P, Point A, Point B){
Vector v = B - A;
return A + v * (Dot(v, P - A) / Dot(v, v));
}
bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2){
//Line1:(a1, a2) Line2:(b1,b2)
double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1),
c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1, a2 - b1);
return dcmp(c1) * dcmp(c2) < && dcmp(c3) * dcmp(c4) < ;
}
bool OnSegment(Point p, Point a1, Point a2){
return dcmp(Cross(a1 - p, a2 - p)) == && dcmp(Dot(a1 - p, a2 -p)) < ;
}
Vector GetBisector(Vector v, Vector w){
Normallize(v), Normallize(w);
return Vector((v.x + w.x) / , (v.y + w.y) / );
} bool OnLine(Point p, Point a1, Point a2){
Vector v1 = p - a1, v2 = a2 - a1;
double tem = Cross(v1, v2);
return dcmp(tem) == ;
}
struct Line{
Point p;
Vector v;
Point point(double t){
return Point(p.x + t * v.x, p.y + t * v.y);
}
Line(Point p, Vector v) : p(p), v(v) {}
};
struct Circle{
Point c;
double r;
Circle(Point c, double r) : c(c), r(r) {}
Circle(int x, int y, int _r){
c = Point(x, y);
r = _r;
}
Point point(double a){
return Point(c.x + cos(a) * r, c.y + sin(a) * r);
}
};
int GetLineCircleIntersection(Line L, Circle C, double &t1, double& t2, vector<Point>& sol){
double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y - C.c.y;
double e = a * a + c * c, f = * (a * b + c * d), g = b * b + d * d - C.r * C.r;
double delta = f * f - * e * g;
if(dcmp(delta) < ) return ;
if(dcmp(delta) == ){
t1 = t2 = -f / ( * e); sol.pb(L.point(t1));
return ;
}
t1 = (-f - sqrt(delta)) / ( * e); sol.pb(L.point(t1));
t2 = (-f + sqrt(delta)) / ( * e); sol.pb(L.point(t2));
return ;
}
double angle(Vector v){
return atan2(v.y, v.x);
//(-pi, pi]
}
int GetCircleCircleIntersection(Circle C1, Circle C2, vector<Point>& sol){
double d = Len(C1.c - C2.c);
if(dcmp(d) == ){
if(dcmp(C1.r - C2.r) == ) return -; //two circle duplicates
return ; //two circles share identical center
}
if(dcmp(C1.r + C2.r - d) < ) return ; //too close
if(dcmp(abs(C1.r - C2.r) - d) > ) return ; //too far away
double a = angle(C2.c - C1.c); // angle of vector(C1, C2)
double da = acos((C1.r * C1.r + d * d - C2.r * C2.r) / ( * C1.r * d));
Point p1 = C1.point(a - da), p2 = C1.point(a + da);
sol.pb(p1);
if(p1 == p2) return ;
sol.pb(p2);
return ;
}
int GetPointCircleTangents(Point p, Circle C, Vector* v){
Vector u = C.c - p;
double dist = Len(u);
if(dist < C.r) return ;//p is inside the circle, no tangents
else if(dcmp(dist - C.r) == ){
// p is on the circles, one tangent only
v[] = Rotate(u, PI / );
return ;
}else{
double ang = asin(C.r / dist);
v[] = Rotate(u, -ang);
v[] = Rotate(u, +ang);
return ;
}
}
int GetCircleCircleTangents(Circle A, Circle B, Point* a, Point* b){
//a[i] store point of tangency on Circle A of tangent i
//b[i] store point of tangency on Circle B of tangent i
//six conditions is in consideration
int cnt = ;
if(A.r < B.r) { swap(A, B); swap(a, b); }
int d2 = (A.c.x - B.c.x) * (A.c.x - B.c.x) + (A.c.y - B.c.y) * (A.c.y - B.c.y);
int rdiff = A.r - B.r;
int rsum = A.r + B.r;
if(d2 < rdiff * rdiff) return ; // one circle is inside the other
double base = atan2(B.c.y - A.c.y, B.c.x - A.c.x);
if(d2 == && A.r == B.r) return -; // two circle duplicates
if(d2 == rdiff * rdiff){ // internal tangency
a[cnt] = A.point(base); b[cnt] = B.point(base); cnt++;
return ;
}
double ang = acos((A.r - B.r) / sqrt(d2));
a[cnt] = A.point(base + ang); b[cnt++] = B.point(base + ang);
a[cnt] = A.point(base - ang); b[cnt++] = B.point(base - ang);
if(d2 == rsum * rsum){
//one internal tangent
a[cnt] = A.point(base);
b[cnt++] = B.point(base + PI);
}else if(d2 > rsum * rsum){
//two internal tangents
double ang = acos((A.r + B.r) / sqrt(d2));
a[cnt] = A.point(base + ang); b[cnt++] = B.point(base + ang + PI);
a[cnt] = A.point(base - ang); b[cnt++] = B.point(base - ang + PI);
}
return cnt;
}
Point ReadPoint(){
double x, y;
scanf("%lf%lf", &x, &y);
return Point(x, y);
}
Circle ReadCircle(){
double x, y, r;
scanf("%lf%lf%lf", &x, &y, &r);
return Circle(x, y, r);
}
//Here goes 3d geometry templates
struct Point3{
double x, y, z;
Point3(double x = , double y = , double z = ) : x(x), y(y), z(z) {}
};
typedef Point3 Vector3;
Vector3 operator + (Vector3 A, Vector3 B){
return Vector3(A.x + B.x, A.y + B.y, A.z + B.z);
}
Vector3 operator - (Vector3 A, Vector3 B){
return Vector3(A.x - B.x, A.y - B.y, A.z - B.z);
}
Vector3 operator * (Vector3 A, double p){
return Vector3(A.x * p, A.y * p, A.z * p);
}
Vector3 operator / (Vector3 A, double p){
return Vector3(A.x / p, A.y / p, A.z / p);
}
double Dot3(Vector3 A, Vector3 B){
return A.x * B.x + A.y * B.y + A.z * B.z;
}
double Len3(Vector3 A){
return sqrt(Dot3(A, A));
}
double Angle3(Vector3 A, Vector3 B){
return acos(Dot3(A, B) / Len3(A) / Len3(B));
}
double DistanceToPlane(const Point3& p, const Point3 &p0, const Vector3& n){
return abs(Dot3(p - p0, n));
}
Point3 GetPlaneProjection(const Point3 &p, const Point3 &p0, const Vector3 &n){
return p - n * Dot3(p - p0, n);
}
Point3 GetLinePlaneIntersection(Point3 p1, Point3 p2, Point3 p0, Vector3 n){
Vector3 v = p2 - p1;
double t = (Dot3(n, p0 - p1) / Dot3(n, p2 - p1));
return p1 + v * t;//if t in range [0, 1], intersection on segment
}
Vector3 Cross(Vector3 A, Vector3 B){
return Vector3(A.y * B.z - A.z * B.y, A.z * B.x - A.x * B.z, A.x * B.y - A.y * B.x);
}
double Area3(Point3 A, Point3 B, Point3 C){
return Len3(Cross(B - A, C - A));
}
class cmpt{
public:
bool operator () (const int &x, const int &y) const{
return x > y;
}
}; int Rand(int x, int o){
//if o set, return [1, x], else return [0, x - 1]
if(!x) return ;
int tem = (int)((double)rand() / RAND_MAX * x) % x;
return o ? tem + : tem;
}
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
void data_gen(){
srand(time());
freopen("in.txt", "w", stdout);
int times = ;
printf("%d\n", times);
while(times--){
int r = Rand(, ), a = Rand(, ), c = Rand(, );
int b = Rand(r, ), d = Rand(r, );
int m = Rand(, ), n = Rand(m, );
printf("%d %d %d %d %d %d %d\n", n, m, a, b, c, d, r);
}
} struct cmpx{
bool operator () (int x, int y) { return x > y; }
};
int debug = ;
int dx[] = {, , , };
int dy[] = {, , , };
//-------------------------------------------------------------------------
ll multi(ll x, ll y, ll mod){
ll lhs = x * (y >> ) % mod * (1ll << ) % mod;
ll rhs = x * (y & ((1ll << ) - )) % mod;
return (lhs + rhs) % mod;
} ll __power(ll a, ll p, ll mod){
ll ans = ;
a %= mod;
while(p){
if(p & ) ans = (ans * a) % mod;
p >>= ;
a = (a * a) % mod;
}
return ans;
} ll power(ll a, ll p, ll mod){
ll ans = ;
while(p){
if(p & ) ans = multi(ans, a, mod);
p >>= ;
a = multi(a, a, mod);
}
return ans % mod;
} ll n;
ll ans[ + ];
bool ok;
void dfs(int pos, ll pre, ll mod){
if(pos == ){
if(pre < 1e11 || power(n, pre, mod) != pre) return;
ans[n] = pre;
ok = ;
return;
}
FOR(i, , ){
ll nex = mod * i + pre;
//try to set next position as i
ll lhs = power(n, nex, mod);
ll rhs = nex % mod;
if(lhs != rhs) continue;
dfs(pos + , nex, mod * );
if(ok) return;
}
}
void solve(){
if(ans[n] != -) return;
ok = ;
dfs(, , );
} //-------------------------------------------------------------------------
int main(){
//data_gen(); return 0;
//C(); return 0;
debug = ;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
if(debug) freopen("in.txt", "r", stdin);
//freopen("in.txt", "w", stdout);
int kase = ;
clr(ans, -);
while(~scanf("%lld", &n) && n){
solve();
printf("Case %d: Public Key = %lld Private Key = %lld\n", ++kase, n, ans[n]);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
return ;
}

code:

LA 4998 Simple Encryption的更多相关文章

  1. UVALive 4998 Simple Encryption --DFS

    题意: 给出K1,求一个12位数(不含前导0)K2,使得K1^K2 mod (10^12) = K2. 解法: 求不动点问题. 有一个性质: 如果12位数K2满足如上式子的话,那么K2%1,K2%10 ...

  2. UVALive 4998 Simple Encryption

    题目描述: 输入正整数K1(K1<=5000),找一个12位正整数K2使得K1K2=K2(mod 1012). 解题思路: 压缩映射原理:设X是一个完备的度量空间,映射ƒ:Χ→Χ 把每两点的距离 ...

  3. uva 12253 - Simple Encryption(dfs)

    题目链接:uva 12253 - Simple Encryption 题目大意:给定K1.求一个12位的K2,使得KK21=K2%1012 解题思路:按位枚举,不且借用用高速幂取模推断结果. #inc ...

  4. UVA12253 简单加密法 Simple Encryption

    这题到现在还是只有我一个人过?太冷门了吧,毕竟你谷上很少有人会去做往年ACM比赛的题 题面意思很简单,每次给出\(K_1\),让你求一个\(K_2\)满足\(K_1^{K_2}\equiv K_2(\ ...

  5. LA 4998简单加密游戏 —— 自相似性质&&不动点迭代

    题意 输入正整数 $K_1$($K_1 \leq 50000$),找一个12为正整数 $K_2$(不能含有前导0)使得 ${K_1}^{K_2} \equiv K_2(mod \ {10}^{12}) ...

  6. What is SSL and what are Certificates?

    Refer to http://www.tldp.org/HOWTO/SSL-Certificates-HOWTO/x64.html The content 1.2. What is SSL and ...

  7. Progressive Scramble【模拟】

    问题 J: Progressive Scramble 时间限制: 1 Sec  内存限制: 128 MB 提交: 108  解决: 45 [提交] [状态] [命题人:admin] 题目描述 You ...

  8. ZOJ 1006:Do the Untwist(模拟)

    Do the Untwist Time Limit: 2 Seconds      Memory Limit: 65536 KB Cryptography deals with methods of ...

  9. Do the Untwist(模拟)

    ZOJ Problem Set - 1006 Do the Untwist Time Limit: 2 Seconds      Memory Limit: 65536 KB Cryptography ...

随机推荐

  1. css 正方体

    <!DOCTYPE html><html lang="zh-cmn-Hans"><head><meta charset="utf ...

  2. 理解运算符 || 和 && 及方法

    || 前面为true的话直接返回前面的值,前面为false的话返回后面的值.如下: console.log(0 || 1); console.log(1 || 0); console.log(1 || ...

  3. Smarty模板

    Smarty模板 是做什么用的?? 是将前端的显示和后台的逻辑进行分离,就相当于把前台显示的页面和后台要实现的某些功能的逻辑给分离出来了,分离在两个文件里,也就是说,前端只负责显示,后端只负责逻辑操作 ...

  4. Java中几种日志方案

    .本文记录Java中几种常用的日志解决方案 0x01 Log4j .这应该是一个比较老牌的日志方案了,配置也比较简单,步骤如下 1)添加对应依赖,比如 Gradle 中 dependencies { ...

  5. iis access denied, you do not have permission.

    this kind of problems are usually caused by some IIS configuration issues, like application pool set ...

  6. Ruby On Rails 环境搭建MySQL数据库连接

    1.  安装wamp1.7.4从而自动安装好Apache和MySQL,Apache的端口可能会被IIS服务占用,可以去控制面板里关掉 2.  修改root密码,为了能在phpMyAdmin里继续操作数 ...

  7. HDU 4512 吉哥系列故事——完美队形(LCIS)

    Problem Description 吉哥这几天对队形比较感兴趣. 有一天,有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h[n],吉哥希望从中挑出一些人,让这些人形成一 ...

  8. POJ 2417 Discrete Logging(离散对数-小步大步算法)

    Description Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 1 ...

  9. git批量删除分支

    要删除本地,首先要考虑以下三点 列出所有本地分支 搜索目标分支如:所有含有'dev'的分支 将搜索出的结果传给删除函数 所以我们可以得到: git br |grep 'dev' |xargs git ...

  10. C++中关于无法解析的外部符号问题LNK2019问题的总结

           网上一般有很全面的解决方法,最近恰好本道长也遇到了这种问题,也恰好解决了,这种问题应该算作配置问题,而非程序本身问题,多数是因为接手了生疏的程序导致,此问题看上去很简单,但木有经验的话很 ...