Loading [MathJax]/jax/element/mml/optable/MathOperators.js

洛谷 P4861 按钮

房间的铁门上有一个按钮,还有一个显示屏显示着“1”。
旁边还有一行小字:“这是一个高精度M进制计算器,每按一次按钮,屏幕上的数便会乘以K。当个位数再次变为1时,门就开了。”
由于Ada急于出去,所以你要在1s之内求出她的最小按键次数。

首先我们看到题目,每次在M进制下对1k,也就是对k乘方,最后还是得到1

这样我们就可以列出同余方程kx1 (mod M)

而初始状态为1,即k0=1

所以答案就是满足方程的最小的正整数x

其实这道题是Ex\_BSGS,因为题目不满足kM互质

考虑我们在做Ex\_BSGS时,每次取出g=gcd(k,M),b=bg,M=Mg,k=kg

得到新方程kx1×kb (mod M)

移项得到kx1bk (mod M)

无解的情况就是g并且b\ne1

证明就不证了,不会的可以去看这篇文章QAQ

直到g=1,即kM互质,就可以用BSGS求解了

而题目给的b1,那么我们回去看这个过程,k,M不互质说明g>1

g>1,x\ne0\Rightarrow g\nmid b\Rightarrow \text{无解}

所以这个题特判下k,M互不互质然后跑BSGS就好了

简单说下BSGS怎么写吧

n=\left \lfloor \sqrt M \right \rfloor,x=i\times n-j,1\le i,j\le n,原方程就变为

k^{i\times n-j}\equiv 1\ (mod\ M)

(k^n)^i\equiv k^j\ (mod\ M)

然后把k^j求出来哈希一下就可以啦

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <cmath>
#define int long long
using namespace std;
int m,k;
map <int,int> f;
int mypow(int a,int x,int p)   //快速幂
{
	int s=1;
	while (x)
	{
		if (x&1)s=s*a%p;
		a=a*a%p;
		x>>=1;
	}
	return s;
}
int gcd(int a,int b)    //最大公约数
{
	if (!b)return a;
	return gcd(b,a%b);
}
signed main()
{
	cin>>m>>k;
	if (gcd(m,k)!=1)     //特判无解
	{
		cout<<"Let's go Blue Jays!"<<endl;
		return 0;
	}
	int n=ceil(sqrt(m)),b=1;
	for (int i=1;i<=n;i++)    //k^j
	{
		b=b*k%m;
		f[b]=i;
	}
	b=1;
	int tmp=mypow(k,n,m);
	for (int i=1;i<=n;i++)    //(k^n)^i
	{
		b=b*tmp%m;
		if (f[b]&&(i*n-f[b]+m)%m!=0)   //有解且不为0
		{
			cout<<(i*n-f[b]+m)%m<<endl;
			return 0;
		}
	}
	cout<<"Let's go Blue Jays!"<<endl;   //无解
	return 0;
}
posted @   eee_hoho  阅读(100)  评论(0编辑  收藏  举报
编辑推荐:
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
阅读排行:
· 从零开始开发一个 MCP Server!
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时
· Browser-use 详细介绍&使用文档
点击右上角即可分享
微信分享提示