AtCoder Beginner Contest 222 G

https://atcoder.jp/contests/abc222/tasks/abc222_g

就是扩展BSGS的应用,\(22.....222\)可以看成\(2 * 11.....111\),然后就是\(2 * (100....0000 - 1) / 9 % k = 0\)

//222....222 % k = 0
//转化完就是求2*(10^x-1)/9 mod k = 0
//等于求 10 ^ x mod k*9/gcd(k,2) =1
//p = k * 9 / gcd(k, 2)
ll exgcd(ll a,ll b,ll &x,ll &y){
    if(!b){
        x=1,y=0;
        return a;
    }
    ll gcd=exgcd(b,a%b,x,y),temp=x;
    x=y,y=temp-a/b*y;
    return gcd;
}

ll inv(ll a,ll p){
    ll x,y;
    if(exgcd(a,p,x,y)!=1) return -1; //无解的情况
    return (x%p+p)%p;
}

const int N = 77773;
int hs[N],head[N], nxt[N], id[N],tp;
void insert(int x,int y) {
    int k=x%N;
    hs[tp] = x,id[tp] = y, nxt[tp] = head[k], head[k] = tp++;
}

int find(int x) {
    int k=x%N;
    for (int i = head[k]; i != -1; i = nxt[i]) if (hs[i] == x) return id[i];
    return -1;
}

ll BSGS(ll a, ll b, ll n) {
    memset(head, -1, sizeof head);
    tp=1;b%=n;
    //if (b == 1)return 0;
    ll m = sqrt(n*1.0),x=1,p=1;
    for(ll i=0; i<m; ++i,p=p*a%n) insert(p*b%n,i);
    for(ll i = m,j;; i+=m) {
        if((j=find(x=x*p%n))!=-1) return i-j;
        if (i > n) break;
    }
    return -1;
}
ll EXBSGS(ll a,ll b,ll p){
    ll tot=1,cnt=0,g=__gcd(a,p);
	a%=p;b%=p;                   //防止超时
    //if(b==1||p==1) return 0;
    while(g>1){
        if(b%g) return -1;    //无法整除则无解
        cnt++;b/=g;p/=g;tot=tot*(a/g)%p;
    	if(tot==b) return cnt;   //na=b说明前面的a的次数为0,只需要返回k
    	g=__gcd(a,p);
    }
	ll res=BSGS(a,b*inv(tot,p)%p,p);
	if(~res) return res+cnt;
	return res;
}

void run() {
    int k; cin >> k;
    k = k * 9;
    if(k % 2 == 0)  k /= 2;
    //10 ^ x % k == 1
    cout << EXBSGS(10, 1, k) << '\n';
    return ;
}
posted @ 2021-10-11 11:13  wlhp  阅读(128)  评论(0)    收藏  举报