luogu 4884 多少个1?

题目描述:

给定整数K和质数m,求最小的正整数N,使得 11111⋯1(N个1)≡K(mod m)

说人话:就是 111...1111 mod m =K

题解:

将两边一起*9+1,左边就是10^ans,然后BSGS即可。

代码:

#include<map>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
ll k,m;
map<ll,int>mp;
ll fastadd(ll x,ll y,ll p)
{
    ll as1 = x*(y>>25)%p*(1ll<<25)%p;
    ll as2 = x*(y&((1<<25)-1))%p;
    return (as1+as2)%p;
}
ll fastpow(ll x,ll y,ll p)
{
    ll ret = 1ll;
    while(y)
    {
        if(y&1)ret=fastadd(ret,x,p);
        x=fastadd(x,x,p);
        y>>=1;
    }
    return ret;
}
ll F2(ll y,ll z,ll p)
{
    ll ret = fastpow(y,p-2,p);
    return fastadd(ret,z,p);
}
ll BSGS(ll y,ll z,ll p)
{
    mp[1]=0;
    ll now = 1,m = (ll)sqrt(p);
    for(int i=1;i<=m;i++)
    {
        now=fastadd(now,y,p);
        if(mp.find(now)==mp.end())
        {
            mp[now]=i;
        }
    }
    ll u = 1;
    for(int i=0;i<=m+2;i++)
    {
        ll tmp = F2(u,z,p);
        if(mp.find(tmp)!=mp.end())
        {
            return mp[tmp]+i*m;
        }
        u=fastadd(u,now,p);
    }
}
int main()
{
    scanf("%lld%lld",&k,&m);
    k = (9ll*k+1ll)%m;
    printf("%lld\n",BSGS(10ll,k,m));
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/LiGuanlin1124/p/10046077.html
今日推荐