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}$$
  • 相关阅读:
    金蝶k3wise 核算项目、辅助资料
    金蝶——“免、抵、退”税操作说明及帐务处理
    阿里云各Linux发行版netcore兼容性评估报告---来自大石头的测试
    金蝶KIS&K3助记码SQL数据库批量刷新
    华为交换机批量加入 Vlan 方法
    华为设备默认console密码
    SQL查询数据并插入新表
    ORACLE删除当前用户下所有的表的方法
    【转】使用Navicat for Oracle新建表空间、用户及权限赋予
    [转]spring mvc注解方式实现向导式跳转页面
  • 原文地址:https://www.cnblogs.com/Rainbowsjy/p/14867872.html
Copyright © 2011-2022 走看看