• luogu P4884 多少个1?


    LINK:多少个1?

    题目要求:(sum_{i=0}^{n-1}10^i equiv k mod m) 最小的n。

    看起来很难求的样子 这个同余式 看起来只能暴力枚举。

    不过既然是同余 我们等式两边就可以同时进行加减乘 运算。

    考虑转换成我们熟悉的模型 而这个形式比较像高次同余方程。

    等式两边同乘 9 再加一 等式变成 (10^nequiv 9*k+1mod m)

    显然这是一个高次同余方程我们直接BSGS即可。

    但是m和10显然有可能是不互质的 所以我们需要一个扩展BSGS (扩展拔山盖世算法。

    哦 m保证为质数 那打扰了。。

    但是 模数有可能m>int 所以我们需要龟速乘 这样的话复杂度就是log^2的了 且log是跑满的。所以非常的慢。

    const ll MAXN=100010;
    ll mod,n;
    map<ll,ll>H;
    inline ll gsc(ll a,ll b)
    {
    	ll cnt=0;
    	while(b)
    	{
    		if(b&1)cnt=(cnt+a)%mod;
    		b=b>>1;a=(a+a)%mod;
    	}
    	return cnt;
    }
    inline ll BSGS()//求 10^x%mod=n; x>1
    {
    	ll w=(ll)sqrt(mod*1.0)+1;
    	ll ww=1;
    	rep(1,w,i)
    	{
    		ww=ww*10%mod;
    		ll cc=gsc(ww,n)%mod;
    		H[cc]=max(H[cc],i);
    	}
    	ll cc=ww;
    	rep(1,w,i)
    	{
    		if(H.find(cc)!=H.end())return i*w-H[cc];
    		if(cc==n)return i*w;
    		cc=gsc(cc,ww)%mod;
    	}
    	return 114514;
    }
    int main()
    {
    	freopen("1.in","r",stdin);
    	get(n);get(mod);
    	n=n*9+1%mod;
    	putl(BSGS());
    	return 0;
    }
    

    其实完全不需要快速幂 我们颠倒一下 两部分先求出右部分即可。

    当然 也可以快速幂了 那个时候不过不能再龟速乘了。

    考虑一种较快的乘法:

    比较常见的 是转long double 的快速乘。

    long double精度不够的时候 会丢弃后面的位。

    考虑 a%p=a-(a/p)p; 那么 ab%p=ab-(ab/p)*p;

    如果p过大的时候 我们会丢掉 a*b后面的一些位 但是这些位同时也产生不了贡献

    所以 这样做是可行的。具体的 我再思考一下。

    inline LL ksc(LL a,LL b,LL p)//long double版本的快速乘
    {
        a%=p;b%=p;
        long long c=(long double)a*b/p;
        long long ans=a*b-c*p;
        if(ans<0) ans+=p;
        else if(ans>=p) ans-=p;
        return ans;
    }
    
  • 相关阅读:
    Python eval 函数妙用
    day19 装饰器
    Struts08---全局结果和全局异常的配置
    Struts07---访问servlet的API
    Struts06---通配符的使用
    Struts05---动态查询
    Struts04---命名空间的查询顺序以及默认执行的Action
    Struts03---参数传递
    Struts02---实现struts2的三种方式
    struts2文件上传和下载
  • 原文地址:https://www.cnblogs.com/chdy/p/12525665.html
Copyright © 2020-2023  润新知