资料来源:https://blog.csdn.net/danliwoo/article/details/48865127
原题见POJ 3696
(不得不说,这哥们的公式是真的6,尝试过手敲之后果断放弃,选择截屏,这大概就是蒟蒻和大佬的差别吧。。)
BSGS
很快想起了BSGS有木有!上篇博客已经讲过这种算法。
/*--------------------------------------------
* File Name: POJ 3696
* Author: Danliwoo
* Mail: Danliwoo@outlook.com
* Created Time: 2015-10-02 22:16:59
--------------------------------------------*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std;
#define N 44725
#define LL long long
#define MOD 150000 //是sqrt(1999999999*9)要求那么大的
LL gcd(LL a, LL b)
{
return b == 0?a:gcd(b, a%b);
}
LL hs[MOD],head[MOD],next[MOD],id[MOD],top;
void insert(LL x, LL y)
{
LL k = x%MOD;
hs[top] = x, id[top] = y, next[top] = head[k], head[k] = top++;
}
LL find(LL x)
{
LL k = x%MOD;
for(LL i = head[k]; i != -1; i = next[i])
if(hs[i] == x)
return id[i];
return -1;
}
LL mult(LL a, LL b, LL c)
{
a %= c; b %= c;
LL ret = 0, tmp = a;
while(b)
{
if(b & 1LL)
{
ret += tmp;
if(ret > c) ret -= c;
}
tmp <<= 1;
if(tmp > c) tmp -= c;
b >>= 1;
}
return ret%c;
}
LL BSGS(LL a,LL b,LL c)
{
memset(head, -1, sizeof(head));
top = 1;
LL m = sqrt(c*1.0), j;
long long x = 1, p = 1;
for(LL i = 0; i < m; ++i, p = p*a%c)
insert(p*b%c, i);//存的是(a^j*b, j)
for(long long i = m; ;i += m)
{
if( (j = find(x = mult(x,p,c))) != -1 )//注意x要用mult()函数否则超LL
return i-j; //a^(ms-j)=b(mod c)
if(i > c)
break;
}
return 0;
}
int main()
{
LL o = 0;
LL n;
while(scanf("%lld", &n), n)
{
printf("Case %d: ", ++o);
LL m = n/gcd(n, 8)*9;
if(gcd(m,10) != 1)
{
printf("0\n");
continue;
}
printf("%lld\n", BSGS(10,1,m));
}
return 0;
}
Euler
还可以试一试欧拉定理。
/*--------------------------------------------
* File Name: POJ 3696
* Author: Danliwoo
* Mail: Danliwoo@outlook.com
* Created Time: 2015-10-02 14:26:08
--------------------------------------------*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std;
#define N 44725
#define LL long long
LL num[N], prim[N];
int cnt = 0;
void get_prim()
{
for(int i = 0;i < N;i++) num[i] = i;
for(int i = 2;i < N;i++) if(num[i])
{
for(int j = i*i;j < N;j += i)
num[j] = 0;
prim[cnt++] = i;
}
}
LL phi(LL n)
{
LL ans = n;
for(int i = 0;prim[i]*prim[i]<=n;i++) if(n%prim[i] == 0)
{
ans -= ans/prim[i];
while(n%prim[i] == 0) n /= prim[i];
}
if(n != 1)
ans -= ans/n;
return ans;
}
LL gcd(LL a, LL b)
{
return b == 0?a:gcd(b, a%b);
}
LL mult(LL a, LL b, LL c)
{
a %= c; b %= c;
LL ret = 0, tmp = a;
while(b)
{
if(b & 1LL)
{
ret += tmp;
if(ret > c) ret -= c;
}
tmp <<= 1;
if(tmp > c) tmp -= c;
b >>= 1;
}
return ret%c;
}
LL po(LL a, LL k, LL m)
{
if(k == 0) return 1;
if(k == 1) return a%m;
LL t = po(a, k/2, m);
t = mult(t, t, m);
if(k & 1LL) t *= a;
return t%m;
}
LL solve(LL x, LL p, LL m, LL f)
{
LL d = po(10, x, m);
if(d == 1)
{
if(x%p == 0)
return solve(x/p, p, m, f+1);
else
return x;
}
if(f == 0) return x;
return x*p;
}
int main()
{
get_prim();
int o = 0;
LL n;
while(scanf("%lld", &n), n)
{
printf("Case %d: ", ++o);
LL m = n/gcd(n, 8)*9;
if(gcd(m,10) != 1)
{
printf("0\n");
continue;
}
if(po(10, 1, m) == 1)
{
printf("1\n");
continue;
}
LL x = phi(m);
LL ans = x, t = x;
for(int i = 0; prim[i]*prim[i] <= x && i < cnt;i++) if(ans%prim[i] == 0)
{
while(t % prim[i] == 0) t /= prim[i];
ans = solve(ans, prim[i], m, 0);
}
if(t != 1)
ans = solve(ans, t, m, 0);
ans = ans == x ? 0 : ans;
printf("%lld\n", ans);
}
return 0;
}