poj 3696 (欧拉函数

    技术2025-10-02  15

    题意: 求出由全8组成的数的最短长度,使得给定的L能整除它

    思路: 整除的时候要往同余的方向想,同余的时候可以往欧拉定理相关想,容易得到9L | 8*(10^x-1),我们是希望 得到10 ^x同余1的形式,这样好解,但8和L可能有公共因子,所以两边除以个gcd(8,L),这样一来 (10 ^x-1)肯定整除9L/gcd(8,L),就好解了,由阶的性质知,答案肯定是phi(9L/gcd(8,L))的因子,枚举即可,模数的范围超过1e9,所以要写快速乘,O(1)快速乘少了个log确实快的飞起,没解的时候其实是gcd(10,9L/gcd(8,L))==1的时候

    #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;} ll fac[100]; ll mul(ll a,ll b,ll p) { if(p<=1000000000)return a*b%p; else if(p<=1000000000000ll)return (((a*(b>>20)%p)<<20)+(a*(b&((1<<20)-1))))%p; } ll mypow(ll a,ll b,ll p) { ll ans=1; while(b){ if(b&1)ans=mul(ans,a,p); a=mul(a,a,p); b>>=1; } return ans; } ll divide(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; } int main() { ll l; int f=0; while(~scanf("%lld",&l)&&l) { ll t=9*l/gcd(8,l); ll sum=divide(t); int cnt=0; for(ll i=1;i*i<=sum;++i) { if(sum%i==0) { fac[++cnt]=i; if(i!=sum/i)fac[++cnt]=sum/i; } } sort(fac+1,fac+1+cnt); bool flag=0; for(int i=1;i<=cnt;++i) if(mypow(10,fac[i],t)==1) { printf("Case %d: %lld\n",++f,fac[i]); flag=1; break; } if(!flag) printf("Case %d: 0\n",++f); } return 0; }
    Processed: 0.015, SQL: 12