hdu 2462 数学欧拉 The Luckiest number

来源:互联网 发布:软件操作说明书模板 编辑:程序博客网 时间:2024/06/06 09:44
题目思路:
求解10^x = 1 (mod 9*L/gcd(L,8))的满足x>0的最小解就是答案
由8构成的数A设有x位
那么A=8(10^0+10^1+...+10^(x-1));
很容易得到A=(8/9)*(10^x-1);
题目的要求就是A=0(mod L)
就是(8/9)*(10^x-1)=0(mod L);
->8*(10^x-1)=0(mod 9L);
->10^x-1=0(mod 9L/gcd(L,8));
->10^x =1 (mod 9L/gcd(L,8));
令p=9*L/gcd(L,i), 等价于10^x==1(mod p),求满足条件的最小的整数x
看到这个式子,我们的第一反应就是数论书上的Euler定理,但是如果gcd(10,p)!=1,即不互素,也就是不满足欧拉定理的条件了,所以此时为no answer.
if(gcd(10,p)==1) 满足欧拉定理, 我们知道10^oula(p)==1(mod p)肯定是满足的;

虽然oula(p)满足上述同余方程,但题目求是最小x,而oula(p)未必是最小的解。考虑到oula(p)不是素数,所以我们就要将oula(p)因子分解,求出oula(p)所有的因子,然后逐个从小到大枚举,如果满足10^x==1(mod p) (其中x为oula(p)的因子),x即为答案。


这题除了思路是思路之外,就是模板题了。。。

#include<stdio.h>#include<math.h>#include<string.h>#include<stdlib.h>#define LL long long#define nmax 134165#define nnum 13000#define num8 8#define num9 9#define num10 10int flag[nmax], prime[nnum], cpfactor[nnum];LL pfactor[nnum], factor[nnum];int plen, len_pfactor, len_factor;void mkprime(){    int i,j;    memset(flag,-1,sizeof(flag));    for(i = 2, plen = 0; i < nmax; i ++){        if(flag[i])            prime[plen ++] = i;        for(j = 0; (j < plen) && (i * prime[j] < nmax); j ++){            flag[ i * prime[j] ] = 0;            if(i % prime[j] == 0)                break;        }    }}int cmp(const void *a, const void *b) {    LL temp = *(LL *) a - *(LL *) b;    if (temp > 0) {        return 1;    } else if (temp < 0) {        return -1;    }    return 0;}LL getPhi(LL n) {//求欧拉函数的值    int i, te;    LL phi;    te = (int) sqrt(n * 1.0);    for (i = 0, phi = n; (i < plen) && (prime[i] <= te); i++) {        if (n % prime[i] == 0) {            phi = phi / prime[i] * (prime[i] - 1);            while (n % prime[i] == 0) {                n /= prime[i];            }        }    }    if (n > 1) {        phi = phi / n * (n - 1);    }    return phi;}LL modular_multi(LL a, LL b, LL c) {// a * b % c    LL res, temp;    res = 0, temp = a % c;    while (b) {        if (b & 1) {            res += temp;            if (res >= c) {                res -= c;            }        }        temp <<= 1;        if (temp >= c) {            temp -= c;        }        b >>= 1;    }    return res;}LL modular_exp(LL a, LL b, LL c) { //a ^ b % c 改成mod_pow就不行,中间发生了溢出,还是这个模板靠谱    LL res, temp;    res = 1 % c, temp = a % c;    while (b) {        if (b & 1) {            res = modular_multi(res, temp, c);        }        temp = modular_multi(temp, temp, c);        b >>= 1;    }    return res;}LL gcd(LL a,LL b){    if(a < b)        a ^= b, b ^= a, a ^= b;    if(b == 0)        return a;    if(!(a & 1) && !(b & 1))        return gcd(a >> 1, b >> 1) << 1;    else if(!(b & 1))        return gcd(a,b >> 1);    else if(!(a & 1))        return gcd(a >> 1,b);    else        return gcd(b,a - b);}void findpFactor(LL n) {    int i, te, cnt;    te = (int) sqrt(n * 1.0);    for (i = 0, len_pfactor = 0; (i < plen) && (prime[i] <= te); i++) {        if (n % prime[i] == 0) {            cnt = 0;            while (n % prime[i] == 0) {                cnt++;                n /= prime[i];            }            pfactor[len_pfactor] = prime[i];//有谁            cpfactor[len_pfactor++] = cnt;//有几个        }    }    if (n > 1) {        pfactor[len_pfactor] = n;        cpfactor[len_pfactor++] = 1;    }}void dfs(int k, LL now) {//求所有质因数的乘积    if (k == len_pfactor) {        factor[len_factor++] = now;        return;    }    int i;    for (i = 0; i < cpfactor[k]; i++) {        now = now * pfactor[k];        dfs(k + 1, now);    }    for (i = 0; i < cpfactor[k]; i++) {        now = now / pfactor[k];    }    dfs(k + 1, now);}void solve(int n) {    int i, d;    LL c, phi;    d = gcd(n, num8);    c = (LL) n;    c = c / d * num9;//先除再乘    if (gcd(num10, c) != 1) {//如果和10不互素        puts("0");//则答案不存在        return;    }    phi = getPhi(c);    findpFactor(phi);    len_factor = 0;    dfs(0, 1);//得到所有phi的因子相乘小于等于phi的乘积    qsort(factor, len_factor, sizeof(factor[0]), cmp);    for (i = 0; i < len_factor; i++) {        if (modular_exp(num10, factor[i], c) == 1) {            printf("%I64d\n", factor[i]);            return;        }    }}#include <iostream>using namespace std;int main() {    int n, cas;    mkprime();    cas = 0;    while (~scanf("%d", &n) && n) {        printf("Case %d: ", ++cas);        solve(n);    }    return 0;}