luogu 4884 多少个1 (BSGS)

很有意思的一个签到题 然而考场上并没有切掉

$1111...111=K(mod\;m)$

$10^{x}=9K+1(mod\;m)$

用$BSGS$求解即可

模数爆了$int$,需要快速乘,然而模数是$10^{11}$级别并不是特别大,可以利用位运算进行$O(1)$快速乘

 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define N1 4000010
 6 #define M1 400010
 7 #define ll long long
 8 #define dd double
 9 #define cll const long long 
10 #define inf 23333333333333333ll
11 using namespace std;
12 
13 ll K,M,A;
14 struct Hsh{
15 #define maxn 4000000
16 int head[N1],nxt[M1],val[M1],cte;ll to[M1];
17 void ins(ll x,int w)
18 {
19     int u=x%maxn; ll v;
20     for(int j=head[u];j;j=nxt[j])
21     {
22         v=to[j];
23         if(v==x) return;
24     }
25     cte++; to[cte]=x; nxt[cte]=head[u];
26     val[cte]=w; head[u]=cte;
27 }
28 int find(ll x)
29 {
30     int u=x%maxn; ll v;
31     for(int j=head[u];j;j=nxt[j])
32     {
33         v=to[j];
34         if(v==x) return val[j];
35     }
36     return -1;
37 }
38 }h;
39 
40 inline ll qmul(ll a,ll b){
41     return ((((a>>25)*b%M)<<25)%M+(a&((1<<25)-1))*b%M)%M;
42 }
43 ll qpow(ll x,ll y)
44 {
45     ll ans=1;
46     while(y){
47         if(y&1) ans=qmul(ans,x);
48         x=qmul(x,x); y>>=1;
49     }return ans;
50 }
51 
52 int main()
53 {
54     scanf("%lld%lld",&K,&M);
55     A=(9ll*K+1)%M;
56     ll sq=sqrt(M),i,pw,now,ans;
57     for(pw=qpow(10ll,sq),now=1,i=1;(i-1)*sq<M;i++) 
58     {
59         now=qmul(now,pw);
60         h.ins(now,i);
61     }
62     for(now=A,ans=inf,i=0;i<sq;i++)
63     {
64         pw=h.find(now);
65         if(pw!=-1) ans=min(ans,pw*sq-i);
66         now=qmul(now,10ll);
67     }
68     printf("%lld\n",ans);
69     return 0;
70 }

 

posted @ 2019-01-10 16:20  guapisolo  阅读(142)  评论(0编辑  收藏  举报