POJ-3696 欧拉定理 公式推导

六眼飞鱼酱① 提交于 2019-12-04 16:01:40

题目链接:https://vjudge.net/problem/POJ-3696

题目大意:给定一个数L,问是否存在这样的kL=88...888,求最小的全是8的数的长度,如果无法构造,输出0

题解思路:

全是8的数可以表示为

   分离分母之后等式变为:

  

是99999这样的数,是9的倍数,要让这个等式成立,唯一分解后的L中质因子2的数量必然小于等于3,如果小于3,就把左右两式子中这部分约去,可得:

gcd变形可得:

  设p=

  q= 

等式为:

,其中p和q互质,且p<q

要让等式成立则必有:

其中k,m,x为未知量,要消去m,x对等式的影响,可以同时对一个已知的数取模

可得:

移项得:

由欧拉定理可知:

  (10和q互质)

如果

  则 

必然无解,输出0

如果互质的话,那么10的指数在 mod q 的条件下的循环节的上限就是

 我们需要枚举所有

的因子,挑出最小的满足

的因子

 

在实现上需要注意的是这里的q会非常大,相对的其欧拉函数也会比较大,需在mod q意义下快速幂计算10^k,并且这里为了防止爆longlong,要手写快速乘。

#include <iostream>
#include <vector>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
using namespace std;
#define ll long long

ll Phi(ll x)
{
    ll ans=x;
    for(int i=2;i*i<=x;i++)
    {
        if(x%i==0)
        {
            ans=ans/i*(i-1);
            while(x%i==0)
            {
                x/=i;
            }
        }
    }
    if(x>1)
    {
        ans=ans/x*(x-1);
    }
    return ans;
}


ll mul(ll a,ll b,ll c)
{
    ll res=0;
    while(b)
    {
        if(b & 1)
        {
            res=(res+a)%c;
        }
        a=(a+a)%c;
        b=b>>1;
    }
    return res;
}

ll quick_pow_mod(ll a,ll b,ll c)
{
    ll res=1;
    while(b)
    {
        if(b & 1)
        {
            res=mul(res,a,c)%c;
        }
        a=mul(a,a,c)%c;
        b=b>>1;
    }
    return res;
}

ll gcd(ll a,ll b)
{
    return b?gcd(b,a%b):a;
}
vector<ll>fac;

void get_factor(ll n)
{
    ll num=n;
    for(ll i=2;i*i<=num;i++)
    {
        if(n%i==0)
        {
            fac.push_back(i);
            while(n%i==0)
            {
                n/=i;
            }
        }
    }
    if(n>1)fac.push_back(n);
}

int main()
{
    ll n;
    for(int kase=1;;kase++)
    {
        fac.clear();
        scanf("%lld",&n);if(n==0)break;

        cout<<"Case "<<kase<<": ";
        ll q=n/gcd(n,8)*9;

        if(gcd(10,q)!=1)
        {
            cout<<0<<endl;
            continue;
        }
        ll phi=Phi(q);
        //cout<<"phi:"<<phi<<endl;
        get_factor(phi);
        sort(fac.begin(),fac.end());
        for(int i=0;i<fac.size();i++)
        {
            while(1)
            {
                phi/=fac[i];
                if(quick_pow_mod(10,phi,q)!=1)
                {
                    phi*=fac[i];
                    break;
                }
                else if(phi%fac[i])
                {
                    break;
                }
            }
        }
        cout<<phi<<endl;
    }

    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!