poj3696 The Luckiest number[欧拉定理]

注意到$L|\frac{8(10^x-1)}{9}$等价于$9L|8(10^x-1)$,这个等价转化一定要记住!(是可以证两者互为充要条件的)

于是整理后有$\frac{9L}{gcd(L,8)}|(10^x-1)$。

转化为同余方程来解决

$10^x \equiv 1 \pmod{\frac{9L}{gcd(L,8)}}$

注意先排除无解情况。也就是说,10和模数必须互质。

若gcd含$2$或者$5$,则肯定无解,很显然。

然后互质前提下发现$\varphi(\frac{9L}{gcd(L,8)})$一定是一个解。(欧拉定理)

于是解的范围被我们明确为了$(0,\varphi(\frac{9L}{gcd(L,8)})]$。

尝试随便找一个数$x$假设$10^x \equiv 1 \pmod{\frac{9L}{gcd(L,8)}}$。

若模数$=qx+r$,$r$是小于等于$x$的一个余数

然后发现$10^{qx} \equiv 1 \pmod{\frac{9L}{gcd(L,8)}}$,

又$10^{qx+r} \equiv 1 \pmod{\frac{9L}{gcd(L,8)}}$。

则$10^r \equiv 1 \pmod{\frac{9L}{gcd(L,8)}}$。

这个说明这个$x$必须是$\varphi(\frac{9L}{gcd(L,8)})$的约数才有可能是解,否则会有更小的解$r$。

于是乎查找范围进一步被缩小为根号个。于是就可以枚举约数检验了。

这题可以使用特殊的快速乘。(现学的)

UPD:当然直接上BSGS也可以。当时不会。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define dbg(x) cerr << #x << " = " << x <<endl
 7 using namespace std;
 8 typedef long long ll;
 9 typedef double db;
10 typedef pair<int,int> pii;
11 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
12 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
16 template<typename T>inline T read(T&x){
17     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
18     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
19 }
20 ll L,p,phi,tmp,ans;
21 int T;
22 inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
23 inline void euler(){
24     tmp=phi=p;
25     for(register ll i=2;i*i<=tmp;++i)if(tmp%i==0){
26         phi=phi/i*(i-1);
27         while(tmp%i==0)tmp/=i;
28     }
29     if(tmp>1)phi=phi/tmp*(tmp-1);
30 }
31 inline ll mul(ll x,ll y){
32     ll X=x*(y>>25)%p*(1<<25)%p;
33     ll Y=x*(y&((1<<25)-1))%p;
34     return (X+Y)%p;
35 }
36 //inline ll mul(ll a,ll b,ll mod){
37 //    return (a*b-(ll)((long double)a/mod*b)*mod+mod)%mod;
38 //}
39 inline ll fpow(ll x,ll k){ll ret=1;for(;k;k>>=1,x=mul(x,x))if(k&1)ret=mul(ret,x);return ret;}
40 
41 int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
42     while(read(L)){
43         p=9*L/gcd(L,8);
44         if(p%2==0||p%5==0){printf("Case %d: 0\n",++T);continue;}
45         euler();ans=1e15;
46         for(register ll i=1;i*i<=phi;++i)if(phi%i==0){
47             if(fpow(10%p,i)==1){ans=i;break;}
48             if(fpow(10%p,phi/i)==1)MIN(ans,phi/i);
49         }
50         printf("Case %d: %lld\n",++T,ans);
51     }
52     return 0;
53 }
View Code

转载于:https://www.cnblogs.com/saigyouji-yuyuko/p/11479098.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值