• bzoj 3031: 理科男


    Description

      吃过草莓刨冰之后,Vani和cl有些疲倦地坐在一个长椅上。
      “呐,玩得开心吗?”Vani忽然问道。
      “嗯……很,很开心的说。”
      “那么,我有一个问题想要问你呢。”
      cl的脸有点红了起来。
      “嗯……好吧。问、问吧……我会告诉你的哦……”
      “那好。对于一个分数A / B……”
      “嗯……哎?哎?!”
      “……就是这个问题。我觉得这个问题好纠结啊……”
      Vani淡定地说完这句话。
      “啊?!哈啊?!”

      对于给定的分数 A / B,求其在 K 进制下是有限小数还是循环小数。如果是有限小数,求小数点后的位数;如果是循环小数,则求混循环部分和循环节的长度又分别是多少。
      注意,循环节指的是最短循环节,且混循环部分的长度也指最短。

    Input

      第一行一个正整数 T,表示测试数据的数目。
      每个测试数据包含三个空格分隔的整数 A, B, K。含义如题目所示。

    Output

      对于每个测试数据,在单独的一行内输出两个空格分隔的整数 M, R。
      其中 M 表示混循环部分的长度,R 表示循环节的长度。
      如果 A / B 在 K 进制下是有限小数,则 R = 0,M 为小数点后面的位数;如果 A / B 在 K 进制下是纯循环小数,则 M = 0。

    $minimizespace M,Rspace s.t.$
    $frac{A}{B}=frac{x}{(K^R-1)K^M}$
    将$frac{A}{B}$化为最简分数后,答案只和$B,K$有关
    若$gcd(B,K)>1$则有混循环部分,将$B$不断除以$gcd(B,K)$直到互质,除的次数即为$M$
    R即为求$frac{B}{gcd(B,K^M)}$在模K意义下与K互质的数构成的乘法群中的阶,答案是$phi(K)$的约数,可以试除得到
    #include<cstdio>
    typedef long long i64;
    i64 gcd(i64 a,i64 b){
        for(i64 c;b;c=a,a=b,b=c%b);
        return a;
    }
    i64 phi(i64 x){
        i64 y=x;
        for(int i=2;i64(i)*i<=x;++i)if(x%i==0){
            y=y/i*(i-1);
            do x/=i;while(x%i==0);
        }
        if(x>1)y=y/x*(x-1);
        return y;
    }
    i64 mul(i64 a,i64 b,i64 p){
        i64 c=0;
        for(;b;b>>=1,a=(a<<1)%p)if(b&1)c=(c+a)%p;
        return c;
    }
    i64 pw(i64 a,i64 n,i64 p){
        i64 v=1;
        for(;n;n>>=1,a=mul(a,a,p))if(n&1)v=mul(v,a,p);
        return v;
    }
    i64 cal(i64 A,i64 B){
        i64 x=phi(B),y=x;
        for(int i=2;i64(i)*i<=x;++i)if(x%i==0){
            while(y%i==0&&pw(A,y/i,B)==1)y/=i;
            do x/=i;while(x%i==0);
        }
        if(x>1&&pw(A,y/x,B)==1)y/=x;
        return y;
    }
    int main(){
        int T;
        for(scanf("%d",&T);T;--T){
            i64 a,b,c;
            scanf("%lld%lld%lld",&a,&b,&c);
            i64 g=gcd(a,b);
            a/=g,b/=g;
            int a1=0;
            while(1){
                i64 x=gcd(b,c);
                if(x==1)break;
                b/=x;
                ++a1;
            }
            printf("%d %lld
    ",a1,b==1?0ll:cal(c,b));
        }
        return 0;
    }
  • 相关阅读:
    程序员的一天
    链表实现回文palindrome判断
    深度探索Go语言:包装方法
    小码哥外挂破解
    Spring中的那些注解
    错误: Unable to connect to a repository at URL 'https://192.168.1.111/svn/
    C#:带校验的串口开关控制
    Crontab不正常执行
    java 注解练习1
    java 注解练习2
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7122675.html
Copyright © 2020-2023  润新知