CF913G Power Substring 数论

看起来是构造题但其实是数学题。对于这种数的构造题就去构造一种情况然后算出来。

假设 \(a\)\(n\) 位,枚举后面有多少位 \(m\) ,设 \(x = a\times 10^m + b , 2^k \bmod{ 10^{n+m} } = x\)

\(m\) 确定,那么 \(b\) 能取一段 \(10^m\) 个不同的数,当 \(10^m \ge 2^{n+m}\) 时一定有解。

我们需要做两步:算 \(b\) ,算 \(k\)

\(k\ge n+m\) 。所以 \(2^{n+m} | 2^k , 2^{n+m}|10^{n+m}\) 所以 \(2^{n+m} | a\times 10^m + b\)

同时由于 \(5 \nmid 2^k\) ,所以 \(5^{n+m} \nmid 2^k , 5^{n+m} \nmid a\times 10^m + b\)

构造 \(b=-a\times {10}^{m} \bmod 2^{n+m}\) ,如果 \(b\)\(5\) 的倍数就再加上 \(2^{n+m}\) ,这样 \(a\times 10^m +b\) 符合条件。(此时还要满足 \(10^m \ge 2^{n+m}\)


让刚才的同余式子两边除以 \(2^{n+m}\) 得到 \(2^{k-n-m} \bmod{ 5^{n+m} } = \dfrac{a\times 10^m + b}{ 2^{n+m} }\)

由于 \(2\)\(5^m\) 的原根,我们可以构造出 \(k\)

这里不能直接 BSGS 了。但可以一步步归纳构造:

首先暴力出 \(d_1\) 使得 \(2^{d_1} \equiv x \pmod 5\)

然后求 \(d_i\) 使得 \(2^{d_i} \equiv x\pmod {5^i}\) 。可以暴力枚举 \(d_{i-1}+j\times \varphi(5^{i-1}),j=0\sim 4\) ,一定有一个满足。(这个结论不太会证)

CF 不让用 __int128 ,只能用龟速乘了。

#include<bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
#define int long long 
using namespace std;
inline int read()
{
    char c=getchar();int x=0;bool f=0;
    for(;!isdigit(c);c=getchar())f^=!(c^45);
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
    if(f)x=-x;return x;
}

inline int mul(int x,int y,int mod){
	int res=0;
	while(y){
		if(y&1)res=(res+x)%mod;
		y>>=1,x=(x<<1)%mod;
	}return res;
}
inline int qpow(int x,int y,int mod){
	int res=1;
	while(y){
		if(y&1)res=mul(res,x,mod);
		y>>=1,x=mul(x,x,mod);
	}return res;
}

void work()
{
	int a=read(),qwq=a,n=0;
	while(qwq)++n,qwq/=10;
	for(int pw10=10,m=1;;m++,pw10*=10)
	{
		int mod=(1ll<<(n+m));
		if(pw10<mod) continue;
		int b=(-a*pw10%mod+mod)%mod;
		if(b%5==0) b+=mod;
		if(b>=pw10)continue;
		int x=(a*pw10+b)/mod;
		int phi=4,pw5=25,res;
		For(i,0,4)
			if(qpow(2,i,5)==x%5){res=i;break;}
	//	cout<<"res "<<res<<" "<<x<<endl;
		for(int i=2;i<=n+m;++i,phi*=5,pw5*=5){
			For(j,0,4)
				if(qpow(2,res+phi*j,pw5)==x%pw5){
					res+=phi*j;
					break;
				}
		}
		res+=m+n;
		cout<<res<<endl;
		return;
	}
}

signed main()
{
	int T=read();
	while(T--)work();
	return 0;
}
posted @ 2021-06-09 17:34  Rainbow_qwq  阅读(64)  评论(0编辑  收藏  举报