解题报告 数数

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.

 

原文地址:https://www.cnblogs.com/SueMiller/p/2207663.html