zoukankan      html  css  js  c++  java
  • CF913G Power Substring 数论

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

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

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

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

    (kge n+m) 。所以 (2^{n+m} | 2^k , 2^{n+m}|10^{n+m}) 所以 (2^{n+m} | a imes 10^m + b)

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

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


    让刚才的同余式子两边除以 (2^{n+m}) 得到 (2^{k-n-m} mod{ 5^{n+m} } = dfrac{a imes 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 xpmod {5^i}) 。可以暴力枚举 (d_{i-1}+j imes varphi(5^{i-1}),j=0sim 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;
    }
    
    $$Huge ext{Goodbye OI}$$
  • 相关阅读:
    约瑟夫环问题
    String常用的工具类
    java 中的==和equals的深度解析
    Intellij IDEA的一些常用设置和使用小技巧
    jvm内存模型概述
    springcloud开篇
    oracle生成path的sql语句
    oracle表空间异常大
    springboot2集成activiti出错
    策略模式2
  • 原文地址:https://www.cnblogs.com/Rainbowsjy/p/14867872.html
Copyright © 2011-2022 走看看