zoukankan      html  css  js  c++  java
  • 题解「P5451 [THUPC2018]密码学第三次小作业」

    校内测试考了这道题,当时按照题目背景瞎搞了搞,把样例水过了,结果爆零/kk

    开始还以为正解要从题目背景中推出来,搞了一个多小时。考完发现背景和题目没什么关系啊!再也不看题目背景了


    首先题面用粗体强调了:(e_1)(e_2) 互素。也就是说,有整数 (s,t),满足:

    [s*e_1+t*e_2= { m{gcd}}(e_1,e_2)=1 ]

    突破口一定是这个式子。

    再看题目中 (m) 是以 (m^{e_1},m^{e_2}) 出现的,上面的那个式子可能要放到指数上。

    这个 ("1") 就很巧妙啊,可以代换到很多地方,比如代进指数的位子上去,并不影响原值。

    则答案

    [m equiv m^1 equiv m^{s*e_1+t*e_2} ({ m {mod}} N) ]

    这个式子又可以写成:

    [m equiv (m^{e_1})^s(m^{e_2})^t ({ m {mod}} N) ]

    把题中所给的 (c_1,c_2) 代入得:

    [m equiv c_1^sc_2^t ({ m {mod}} N) ]

    (s,t)显然可以用扩展欧几里得算法求得,所以答案即为 (c_1^sc_2^t { m {mod}} N)

    极大数求幂显然要用到快速幂,而 (s,t) 可能为负数,快速幂就没法求了。所以我们需要把指数转变为正数求解。

    运用所学初中知识:

    [c^x=(c^{-1})^{-x} ]

    使用扩展欧几里得算法求解逆元即可。


    另外,快速幂和计算 (c_1^sc_2^t) 时要用龟速乘,否则第二个点爆 long long


    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #define lxl long long
    #define debug(x) printf("debug : %lld
    ", x)
    using namespace std;
    
    inline lxl fti(lxl a,lxl b,lxl p)
    {
    	lxl ans=0;
    	while(b>0)
    	{
    		if(b&1) ans=(ans+a)%p;
    		a=(a+a)%p;
    		b>>=1;
    	}
    	return ans;
    }
    
    inline lxl fmi(lxl a,lxl b,lxl p)
    {
    	lxl ans=1;
    	a%=p;
    	while(b>0)
    	{
    		if(b&1) ans=fti(ans,a,p);
    		a=fti(a,a,p);
    		b>>=1;
    	}
    	return ans%p;
    }
    
    inline lxl exgcd(lxl a,lxl b,lxl &x,lxl &y)
    {
    	if(!b) {x=1,y=0;return a;}
    	lxl k=exgcd(b,a%b,x,y);
    	lxl z=x;x=y,y=z-a/b*y;
    	return k;
    }
    
    inline lxl inv(lxl a,lxl b)
    {
    	lxl x,y;
    	lxl g=exgcd(a,b,x,y);
    	return g==1?(x%b+b)%b:-1;
    }
    
    lxl c1,c2,e1,e2,N;
    
    int main()
    {
    	//freopen("P5451.in","r",stdin);
    	int t;scanf("%d",&t);
    	while(t--)
    	{
    		scanf("%lld%lld%lld%lld%lld",&c1,&c2,&e1,&e2,&N);
    		lxl s,t,g=exgcd(e1,e2,s,t);
    		if(s<0) c1=inv(c1,N),s=-s;
    		if(t<0) c2=inv(c2,N),t=-t;
    		printf("%lld
    ",fti(fmi(c1,s,N),fmi(c2,t,N),N));
    	}
    	return 0;
    }
    
  • 相关阅读:
    k8s之pod与Pod控制器
    使用kubeadm部署k8s
    lamp架构
    数据库安装和基本操作
    mysql基础
    Helm Chart 一键部署 Jenkins
    使用 Helm Chart 部署及卸载 istio
    使用 chart 部署 skywalking
    豆瓣电影TOP250和书籍TOP250爬虫
    如何使用 Skywalking Agent ?
  • 原文地址:https://www.cnblogs.com/syc233/p/12855512.html
Copyright © 2011-2022 走看看