zoukankan      html  css  js  c++  java
  • 解题报告 数数

    1.        题目

    数数

    【问题描述】

    给定n,m,k都是小于等于10001的正整数,输出给定的n个数中,其m次能被k整除的数的个数

    【输入格式】

    有两行组成,第一行是三个整数n,m,k

    第二行是n个正整数 都不超过10001

    【输出格式】

    输出满足条件的数的个数

    【样例输入】count.in

    3 2 50

    9 10 11

    【样例输出】count.out

    1

     

    2.        题目实质

    判断给定数的 m 次幂能否被 k 整除。

    3.        算法

    第一种思路是,将这个数的 m 次幂求出来,然后直接判断。方法是快速幂。但是,理论上讲,这么做是要用到高精的。不过可以每计算一次就 mod 一次或者是约分一次,这样可以不用高精。

     

    然后,第二种思路。

    当一个数可以整除 k 时,它的每一个质因子的指数都应大于等于 k 的对应质因子的指数。(这么白痴的定理我就不用证明了吧?)

    所以,我们可以先对 k 进行分解质因数,将它的每一个质因子的指数存起来,然后再将给定的那个数分解质因数,将它的每一个质因子的指数乘以 m 。(这样就相当于对它的 m 次幂分解质因数了)然后,判断 k 有没有比这个数的 m 次幂多出的质因子,或是某个质因子的指数比这个数的 m 次幂更高。

    然后,然后就是这样。

    4.        注意事项

    快速幂要及时 mod 或是约分。

    分解质因数要预处理出质数表,然后要将 k 和指定的这个数的质因子都判断一下,不要只判断这个数的质因子,不然会判断不全。

    5.        代码

    快速幂(艾 FHAI)

    var

    x,ans,i,n,m,k:longint;

     

    procedure check(r,m,k:longint);

    var

    i,t:longint;

    begin

    t:=r;dec(m);

    while m<>0 do

        begin

        if m mod 2<>0 then t:=(t*r)mod k;

        m:=m div 2;

        t:=(t*t)mod k;

        end;

    {t:=1;

    for i:=1to m do

         t:=(t*r)mod k;  }

    if t=0 then inc(ans);

    end;

     

    begin

    assign(input,'count.in');reset(input);

    assign(output,'count.out');rewrite(output);

    readln(n,m,k);

    for i:=1 to  n do

         begin

         read(x);

         check(x,m,k);

         end;

    writeln(ans);

    close(input);close(output);

    end.

     

     

     

    分解质因数 (SueMiller)

    var v:array[0..20000]of boolean;

        f:array[0..20000]of longint;

        g1,g2:array[0..20000]of longint;

        i,j,nn,nk:longint;

        n,m,k:longint;

        p,ans:longint;

        flag:boolean;

    begin

      assign(input,'count.in');reset(input);

      assign(output,'count.out');rewrite(output);

     

      fillchar(v,sizeof(v),false);

      for i:=2 to 20000 do

        if not v[i] then

          begin

            j:=i;

            while j+i<20000 do

              begin

                j:=j+i;

                v[j]:=true;

              end;

          end;

     

      readln(n,m,k);

      fillchar(f,sizeof(f),0);

      fillchar(g1,sizeof(g1),0);

      nn:=0;

      nk:=0;

      for i:=2 to 20000 do

        if not v[i] then begin

          inc(nn);

          f[nn]:=i;

          while k mod i=0 do

            begin

              k:=k div i;

              inc(g1[nn]);

            end;

          if (k=1) and (nk=0) then nk:=nn;

        end;

      if k<>1 then

        begin

          writeln(0);

          close(input);close(output);

          halt;

        end;

     

      ans:=0;

      for i:=1 to n do

        begin

          read(p);

          flag:=false;

          j:=0;

          fillchar(g2,sizeof(g2),0);

          if (p=1) and (k<>1) then continue;

          if (p=0) and (k<>0) then continue;

          repeat

            inc(j);

            while p mod f[j]=0 do

              begin

                p:=p div f[j];

                inc(g2[j]);

              end;

     

            g2[j]:=g2[j]*m-g1[j];

    //        writeln('&&&   ',p,' ',g2[j]);

    //        g1[j]:=0;

            if g2[j]<0 then begin flag:=true; break end;

    //        writeln('**  ',g2[j],' ',g1[j],'        ',j) ;

          until j>=nk;

     

    //      for j:=1 to nk do

    //        if g1[j]<>0 then continue;

     

          if not flag then inc(ans);

        end;

      writeln(ans);

     

      close(input);close(output);

    end.

     

  • 相关阅读:
    Linux 基本操作 (day2)
    Linux 简介(day1)
    python 反射、md5加密
    Python 简易版选课系统
    python 类与类之间的关系
    python 基本运算符
    python 基础操作--数据类型
    python初识
    生成器和生成器表达式
    SpringMvc测试框架详解----服务端测试
  • 原文地址:https://www.cnblogs.com/SueMiller/p/2207663.html
Copyright © 2011-2022 走看看