【CF913G】Power Substring 数论+原根

【CF913G】Power Substring

题意:T组询问,每次给定一个数a,让你求一个k,满足$2^k$的10进制的后$min(100,length(k))$位包含a作为它的子串。你只需要输出一个k,不需要最小化k的值,保证有解。

$T\le 2000,a\le 10^{11}$

题解:神题。

假设a有n位,$2^k=x$,$x=a\times 10^m+b(\mod 10^{n+m})$,我们显然有$k\ge n+m$,所以$2^{n+m}\mid x$,又因为$2^{n+m}\mid 10^{n+m}$,则$2^{n+m}\mid a\times 10^m+b$(等式1)。因为$5^{n+m}\nmid x$,$5^{n+m}\mid 10^{n+m}$,所以$5^{n+m}\nmid a\times 10^m+b$(等式2)。当m确定时,b的取值范围就是一段连续的、长度为$10^m$的区间,所以当$10^m\ge 2^{n+m}$时一定有解,所以m不会太大,我们考虑枚举m。

当m确定时,我们可以根据上面那两条等式快速求出b的值,但如何根据b的值反推得到x的值呢?我们发现等式1的左右两端都能被$2^{n+m}$整除,所以将其除以$2^{n+m}$,得到$y=w (\mod 5^{n+m}),w=\frac {a\times 10^m+b} {2^{n+m}}$。容易证明如下引理:

引理:对于任意$m\le 1$,2是$5^m$的原根。

证明:首先通过枚举可知2是5的原根,$2^i=2,4,3,1,2,....$,循环节为4。

熟悉原根的都知道,a是p的原根当且仅当:将$\varphi(p)$分解质因数变成$\prod p_i^{e_i}$后,对于任意的i,$a^{\frac {\varphi(p)} {p_i}}\neq 1 (\mod p)$。那么当$m\ge 2$时,$\varphi(5^m)$分解质因数形式为$2^2\times 5^{m-1}$,有$2^{4\times 5^{m-2}}=(2^{5^{m-2}})^4=2^4(\mod p^2)$,且$2^{2\times 5^{m-1}}=2^2(\mod p^2)$,二者在$\mod p^a$意义下显然不为1。所以2是$p^m$的原根。

现在我们只需要求出$w$的指标就好了,这里求指标的方法采用了归纳的思想:

1.我们先暴力求出$w$在$\mod 5$意义下的指标$d_1$。
2.我们希望从w在$\mod 5^m$意义下的指标$d_m$推导出w在$\mod 5^{m+1}$意义下的指标$d_{m+1}$,发现对于$j\in\{0,1,2,3,4\}$,存在唯一的j使得$2^{d_m+j}=1(\mod 5^{m+1})$。所以我们暴力枚举j即可。

注意最后这一步采用快速幂会爆long long,所以还要用快速乘。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int T,n,m;
ll x,y,a,b;
inline ll ps(ll x,ll y,ll P)
{
	ll z=0;
	while(y)
	{
		if(y&1)	z=z+x;
		x<<=1,y>>=1;
		if(x>=P)	x-=P;
		if(z>=P)	z-=P;
	}
	return z;
}
inline ll pm(ll x,ll y,ll P)
{
	ll z=1;
	x%=P;
	while(y)
	{
		if(y&1)	z=ps(z,x,P);
		x=ps(x,x,P),y>>=1;
	}
	return z;
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%lld",&a);
		ll t=a,m1=1;
		n=0;
		while(t)	t/=10,n++;
		for(m=0;;m++,a*=10,m1*=10)
		{
			b=(-a)&((1<<(n+m))-1);
			if((a+b)%5==0)	b+=1<<(n+m);
			if(b>=m1)	continue;
			x=a+b,y=x>>(n+m);
			int i,j;
			ll now=0,phi,pw;
			for(i=0;i<4;i++)	if(pm(2,i,5)==y%5)	now=i;
			phi=4,pw=5;
			for(i=2;i<=n+m;i++)
			{
				pw*=5;
				for(j=0;j<5;j++)	if(pm(2,now+j*phi,pw)==y%pw)
				{
					now+=j*phi;
					break;
				}
				phi*=5;
			}
			printf("%lld\n",now+n+m);
			break;
		}
	}
	return 0;
}//1 5

原文地址:https://www.cnblogs.com/CQzhangyu/p/8282547.html

时间: 2024-08-29 09:01:31

【CF913G】Power Substring 数论+原根的相关文章

51Nod1039 N^3 Mod P 数论 原根 BSGS

原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1039.html 题目传送门 - 51Nod1039 题意 题解 这题我这个做法要卡常数. 不好意思我只是来存代码的. 代码 #include <bits/stdc++.h> using namespace std; const int N=100005; int T,A,B,P; int Fac_p[N],Fac_tot,g; int prime[N],vis[N],pcnt=0; void G

判断一个int型数字是否是自守数

自守数 如果某个数的平方的末尾几位数等于这个数,那么就称这个数为自守数. 显然,5和6是一位自守数(5x5=25 6x6=36),25x25=625 76x76=5776,所以25和76是两位自守数. 详细描述: 接口说明 原型: Public static boolean isAutoMorphicNum( int num) 输入参数: num 需要判断的数 输出参数(指针指向的内存区域保证有效): 无 返回值: true 是自守数 false 不是自守数 涉及知识点: JAVA语言基础:数字

Power Sum 竟然用原根来求

Power Sum Time Limit: 20000/10000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitStatus Problem Description 给出n,m,p,求 (1^m + 2^m + 3^m + 4^m + ... + n^m) % p Input 第一行一个数T( <= 10),表示数据总数 然后每行给出3个数n,m,p(1 <= n <= m <= 10^18, 1

poj 1284 Primitive Roots 【原根】【数论】

题目链接 :传送门 题目大意: 求一个质数的原根个数. 先普及一下原根的定义: 设m是正整数,a是整数,若a模m的阶等于euler(m),则称a为模m的一个原根. eg: m=7,euler(7) =  6(1,2,3,4,5,6) 则: 1   1^(n)mod7=1! = 6 2   2^(n)mod7={2 4 1}!=6 3   3^(n)mod7={3,2,6,4,5,1}==6   故3是模7的原根 4   4^(n)mod7={4,2,1}!=6 5   5^(n)mod7={5,

数论入门2——gcd,lcm,exGCD,欧拉定理,乘法逆元,(ex)CRT,(ex)BSGS,(ex)Lucas,原根,Miller-Rabin,Pollard-Rho

数论入门2 另一种类型的数论... GCD,LCM 定义\(gcd(a,b)\)为a和b的最大公约数,\(lcm(a,b)\)为a和b的最小公倍数,则有: 将a和b分解质因数为\(a=p1^{a1}p2^{a2}p3^{a3}...pn^{an},b=p1^{b1}p2^{b2}p3^{b3}...pn^{bn}\),那么\(gcd(a,b)=\prod_{i=1}^{n}pi^{min(ai,bi)},lcm(a,b)=\prod_{i=1}^{n}pi^{max(ai,bi)}\)(0和任何

[CodeForces - 1225D]Power Products 【数论】 【分解质因数】

[CodeForces - 1225D]Power Products [数论] [分解质因数] 题目描述 Time limit 2000 ms Memory limit 524288 kB Source Technocup 2020 - Elimination Round 2 Tags hashing math number theory *1900 Site https://codeforces.com/problemset/problem/1225/D 题面 Example Input 6

NTT(快速数论变换)用到的各种素数及原根

NTT(快速数论变换)用到的各种素数及原根 g是mod(r * 2 ^ k + 1)的原根 r * 2 ^ k + 1 r k g 3 1 1 2 5 1 2 2 17 1 4 3 97 3 5 5 193 3 6 5 257 1 8 3 7681 15 9 17 12289 3 12 11 40961 5 13 3 65537 1 16 3 786433 3 18 10 5767169 11 19 3 7340033 7 20 3 23068673 11 21 3 104857601 25 2

【数论】【原根】原根的性质以及如何求原根

一个数m如果有原根,则其原根个数为phi(phi(m)).特别地,对素数有phi(p)=p-1. 假设g是奇素数p的一个原根,则g^1,g^2,...,g^(p-1)在模p意义下两两不同,且结果恰好为1~p-1,由此可以定义"离散对数",与连续数学中的对数有异曲同工之妙. 离散对数又叫做"指标",有指标法则:I(ab)≡I(a)+I(b) (mod p-1):I(a^k)≡k*I(a) (mod p-1),由此可以把乘法转化为加法. 指标的求法: #include&

Leetcode 342 Power of Four 数论

题意:判断一个数是不是4的幂数,和Power of two类似. 先判断num是否大于0,再判断num是否能开根号,最后判断num开根号后的数是否是2^15的约数. 提示:4的幂数开根号就是2的幂数. 注意:判断一个双精度数a是否是0,请用fabs(a)<一个极小的数,如本题中用的是1e-9. 1 class Solution { 2 public: 3 bool isPowerOfFour(int num) { 4 return (num > 0 ) && (fabs((in