ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

BZOJ1409 Password 题解

2022-07-28 16:31:06  阅读:122  来源: 互联网

标签:加密 Matrix int 题解 BZOJ1409 rm Password final const


\(\mathrm{Describe.}\)

一种新的密码被研发出来了。想使用密码,首先需要用种子 \(\rm p\) 生成加密序列。具体的:

\(\rm E_i= p\ \ \ \ i=1,2\)

\(\rm E_i=E_{i-1}\times E_{i-2}\ \ \ i>2\)

之后,每次给出两个数 \(\rm n,q\),输出加密后的数字 \(\rm d\)。具体的加密方法为:

\(\rm d=E_n\ \%\ q\)

其中,\(\rm 0<n,q<2^{31},0<q<p,0<m\leq 5000\)

\(\mathrm{Solution.}\)

首先观察发现加密序列的指数是斐波那契数列,即,生成的序列形如:

\(\rm p^1,p^1,p^2,p^3,p^5......\)

又因为 \(\rm n\) 是 \(2^{31}\) 的量级,所以可以使用矩阵快速幂加速求出斐波那契数列。但是即使是这样的话这个指数本身依然大的离谱,无法接受。继续观察最终加密方法的数学式子,可以发现这个式子可以使用欧拉降幂处理。其中欧拉降幂:

\(\rm a^b\ \%\ c=a^{b\%\phi(c)+\phi(c)}\ \%\ c\)

所以我们可以把在求斐波那契数列时的 \(\rm mod\) 设置为 \(\phi(c)\),这样求出来的 \(\rm p\) 的指数就合理可计算了。

之后写个快速幂就好了。

\(\mathrm{Code.}\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int prime[N],cnt;
bool vis[N];
int m,p,q,n,MOD;
struct Matrix
{
	int mat[2][2];
}fib,final;

Matrix operator*(const Matrix &x,const Matrix &y)
{
	Matrix tmp;
	for(int i=0;i<=1;i++)
		for(int j=0;j<=1;j++)
			tmp.mat[i][j]=0;
	
	for(int i=0;i<=1;i++)
		for(int j=0;j<=1;j++)
			for(int k=0;k<=1;k++)
				tmp.mat[i][j]+=x.mat[i][k]*y.mat[k][j]%MOD,
				tmp.mat[i][j]%=MOD;
	return tmp;
}

int qpow(int a,int n)
{
	int ans=1;
	while(n)
	{
		if(n&1) ans=ans*a%q;
		a=a*a%q;
		n>>=1;
	}
	return ans;
}

int read()
{
	int x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9')
	{
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9')
	{
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}
void Prime_Init()
{
	for(int i=2;i<=N-5;i++)
	{
		if(!vis[i]) prime[++cnt]=i;
		for(int j=1;i*prime[j]<=N && j<=cnt; j++)
		{
			vis[i*prime[j]]=true;
			if(!(i%prime[j])) break;
		}
	}
}
int getphi(int n)
{
	int ans=n;
	for(int i=1;prime[i]*prime[i]<=n;i++)
	{
		while(!(n%prime[i]))
		{
			ans=ans/prime[i]*(prime[i]-1);
			while(!(n%prime[i])) n/=prime[i];
		}
	}
	if(n!=1) ans=ans/n*(n-1);
	return ans;
}
signed main()
{
	Prime_Init();
	m=read(),p=read();
	while(m--)
	{
		n=read(),q=read();
		int phiq=getphi(q);
		MOD=phiq;
		fib.mat[0][0]=fib.mat[0][1]=fib.mat[1][0]=1;
		fib.mat[1][1]=0;
		final.mat[0][0]=final.mat[1][1]=1;
		final.mat[1][0]=final.mat[0][1]=0;
		
		while(n)
		{
			if(n&1) final=final*fib;
			fib=fib*fib;
			n>>=1;
		}
		
		int final_ans=qpow(p,final.mat[0][1]%MOD+MOD)%q;
		printf("%d\n",final_ans);
	}
	return 0;
}

标签:加密,Matrix,int,题解,BZOJ1409,rm,Password,final,const
来源: https://www.cnblogs.com/juruo-wsy/p/16529127.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有