poj 3696 (欧拉函数

题意:
求出由全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; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值