luogu P4884 【多少个1?】

最近在学数论,于是来写这道bsgs模板题。

  • 正文

题意比较明确,要求

最小的n使得\(111...111\)一共n个\(1\),能膜\(m\)\(k\)

即为求

\[111...111 \equiv k \ (mod \ m) \]

\(111...111\)的位数\(n\)的最小值。

乍看之下没有思路,但是可以发现把这个数乘\(9\)再加\(1\),就是\(10^{n}\)

由于同余式两边乘或加某数,依然成立。所以把左右乘\(9\)\(1\)

就变成了求

\[10^{n} \equiv 9k+1 \ (mod \ m) \]

\(n\)的最小值。

这个式子就可以用bsgs算法来求

不会bsgs可以去OI-wiki看看。

  • 注意

在bsgs计算过程中会爆long long,只开long long会WA后面两个点。要用快(龟)速

乘 或 __int128存数。

\(Code\):

#include <iostream>
#include <cstdio>
#include <cmath>
#include <map>
using namespace std;
#define int __int128
inline int read(){
	register int x=0,f=0,ch=getchar();
	while('0'>ch||ch>'9')f^=ch=='-',ch=getchar();
	while('0'<=ch&&ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=getchar();
	return f?-x:x;
}
inline void print(int x){
	if(x<10){
		putchar(x+'0');
		return ;
	}else print(x/10);
	putchar(x%10+'0');
}
map<int,int>vis;
inline int qpow(int x,int p,int P){
	register int res=1;
	for(;p;p>>=1,x=x*x%P)if(p&1)res=res*x%P;
	return res%P;
}
int p,n,m,res,ans=1,Ans; 
signed main(){
	n=read()*9+1,p=read();n%=p;
	m=ceil(sqrt((long long)p));
	res=qpow(10,m,p)%p;
	vis[n%p]=0;
	for(register int i=1;i<=m;++i)
		vis[qpow(10,i,p)*n%p]=i;
	for(register int i=1;i<=m;++i){
		ans=ans*res%p;
		if(vis[ans]){
			Ans=i*m%p-vis[ans];
			print((Ans%p+p)%p);
			return 0;
		}
	}
	return 0;
}


posted @ 2020-03-04 18:42  Lates  阅读(126)  评论(0)    收藏  举报