洛谷:多少个1?(BSGS)

题目描述

给定整数KK和质数mm,求最小的正整数NN,使得 11\cdots111⋯1(N个1) \equiv K \pmod m≡K(modm)

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

输入输出格式

输入格式:

 

第一行两个整数,分别表示KK和mm

 

输出格式:

 

一个整数,表示符合条件最小的NN

 

输入输出样例

输入样例#1: 复制

9 17

输出样例#1: 复制

3

说明

30%的数据保证m\leq 10^6m≤106

60%的数据保证m\leq 5*10^7m≤5∗107

100%的数据保证2\leq m\leq 10^{11},0\leq K< m2≤m≤1011,0≤K<m

思路:即求最小的n满足(pow(10, n)-1)/9 % m = k。化简一下pow(10, n) % m = 9*k+1, BSGS即可,模数较大用__int128。

# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef __int128 Int;
Int a,b,c,m;
map<Int,Int>mp;
inline Int read() {
    Int X=0,w=1; char c=getchar();
    while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
    while (c>='0'&&c<='9') X=(X<<3)+(X<<1)+c-'0',c=getchar();
    return X*w;
}
inline void out(Int x){
    if(x/10) out(x/10);
    putchar(x%10+'0');
}
Int qsm(Int x){
    Int sum = 1, aa = a;
    for(;x;x>>=1){
        if(x&1) sum=sum*aa%c;
        aa = aa*aa%c;
    }
    return sum;
}
Int solve(){
    mp.clear();
    /*if (a%c==0){   //判断a,c 是否互质,因为c 是质数,所以直接判断是否整除即可
        printf("no solution\n");
        continue;
    }*/
    int p=false;
    m=(Int)ceil(sqrt((double)c));
    Int ans;
    for (Int i=0;i<=m;i++){
        if (i==0){
            ans=b%c;
            mp[ans]=i;
            continue;
        }
        ans = ans*a%c;
        mp[ans]=i;
    }
    Int t = qsm(m); ans=1;
    for(Int i=1;i<=m;i++){
        ans = ans*t%c;
        if(mp[ans]){
            Int t=i*m-mp[ans];
            return (t%c+c)%c;
            p=true;
            break;
        }
    }
    //if(!p) printf("no solution\n");
}
int main(){
    LL K, M;
    K = read();
    M = read();
    a = 10;
    b = 9*K+1;
    c = M;
    out(solve());
    puts("");
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值