切换到宽版
  • 15914阅读
  • 11回复

『求助』NOIP2005 普及组第四题 [复制链接]

上一主题 下一主题
离线archimedes
 

只看楼主 倒序阅读 0 发表于: 2005-11-21
循环(CIRCLE.PAS/C/CPP)

求一个正整数n的正整数次幂的后k位是否会发生循环?如果是,循环长度是多少?
[ 此贴被sammy312在2005-12-06 19:07重新编辑 ]
离线archimedes

只看该作者 1 发表于: 2005-11-24
怎么没人?
离线stevenjl

只看该作者 2 发表于: 2005-11-25
原题目……
Dream Walker...
离线archimedes

只看该作者 3 发表于: 2005-11-29
原题目

循环
(circle.pas/c/cpp)
【问题描述】

乐乐是一个聪明而又勤奋好学的孩子。他总喜欢探求事物的规律。一天,他突然对数的正整数次幂产生了兴趣。
众所周知,2的正整数次幂最后一位数总是不断的在重复2,4,8,6,2,4,8,6……我们说2的正整数次幂最后一位的循环长度是4(实际上4的倍数都可以说是循环长度,但我们只考虑最小的循环长度)。类似的,其余的数字的正整数次幂最后一位数也有类似的循环现象:
          循环             循环长度
2     2、4、8、6             4
3     3、9、7、1             4
4     4、6                       2
5     5                           1
6     6                           1
7     7、9、3、1             4
8     8、4、2、6             4
9     9、1                       2
这时乐乐的问题就出来了:是不是只有最后一位才有这样的循环呢?对于一个整数n的正整数次幂来说,它的后k位是否会发生循环?如果循环的话,循环长度是多少呢?
注意:
1. 如果n的某个正整数次幂的位数不足k,那么不足的高位看做是0。
2. 如果循环长度是L,那么说明对于任意的正整数a,n的a次幂和a + L次幂的最后k位都相同。

【输入文件】

输入文件circle.in只有一行,包含两个整数n(1 <= n < 10100)和k(1 <= k <= 100),n和k之间用一个空格隔开,表示要求n的正整数次幂的最后k位的循环长度。

【输出文件】

输出文件circle.out包括一行,这一行只包含一个整数,表示循环长度。如果循环不存在,输出-1。

【样例输入】

32 2

【样例输出】

4

【数据规模】

对于30%的数据,k <= 4;
对于全部的数据,k <= 100。
[ 此贴被sammy312在2005-11-29 19:34重新编辑 ]
离线eerrooo
只看该作者 4 发表于: 2005-11-29
program circle;
type
num=record
    p:byte;
    n:array[1..100] of integer;
    end;
var
can:boolean;
code,k,i,j:integer;
st:string;
n,n2:num;
f,a:array[0..100] of num;
now:array[0..10] of num;
function multiply(x,y:num;k:byte):num;
var
  i,j:integer;
  z:num;
begin
  z.p:=x.p+y.p-1;
  if z.p>k then z.p:=k;
  fillchar(z.n,sizeof(z.n),0);
  for i:=1 to y.p do
    begin
    z.n:=z.n+x.n[1]*y.n;
    for j:=2 to x.p do
      begin
        if i+j-1>k then break;
        z.n[i+j-1]:=z.n[i+j-1]+x.n[j]*y.n;
        z.n[i+j-1]:=z.n[i+j-1]+z.n[i+j-2] div 10;
        z.n[i+j-2]:=z.n[i+j-2] mod 10;
      end;
    end;
  while (z.n[z.p]>=10)and(z.p<k) do
    begin
    inc(z.p);
    z.n[z.p]:=z.n[z.p-1] div 10;
    z.n[z.p-1]:=z.n[z.p-1] mod 10;
    end;
  z.n[z.p]:=z.n[z.p] mod 10;
  multiply:=z;
end;
function same(x,y:num;k:byte):boolean;
var
  i:integer;
begin
  same:=false;
  for i:=k downto 1 do
    if x.n<>y.n then
    exit;
  same:=true;
end;
begin
assign(input,'circle.in');
reset(input);
readln(st);
close(input);
val(copy(st,pos(' ',st)+1,length(st)-pos(' ',st)),k,code);
delete(st,pos(' ',st),length(st)-pos(' ',st)+1);
n.p:=k;
fillchar(n.n,sizeof(n.n),0);
if length(st)>k then delete(st,1,length(st)-k);
for i:=1 to length(st) do
  n.n:=ord(st[length(st)-i+1])-48;
f[0].p:=1;f[0].n[1]:=1;a[0]:=n;
f[k].p:=1;f[k].n[1]:=-1;
for i:=1 to k do
  begin
    fillchar(now,sizeof(now),0);
    now[0]:=n;n2.p:=1;n2.n[1]:=1;can:=false;
    for j:=1 to 10 do
    begin
      now[j]:=multiply(now[j-1],a[i-1],i);
      n2:=multiply(n2,a[i-1],k);
      if same(now[j],now[0],i) then
        begin
        a:=n2;
        n2.p:=1;n2.n[1]:=j;
        f:=multiply(f[i-1],n2,100);
        can:=true;
        break;
        end;
    end;
    if not can then break;
  end;
assign(output,'circle.out');
rewrite(output);
for i:=f[k].p downto 1 do write(f[k].n);
writeln;
close(output);
end.

【小结】

本题的特殊性在于,利用递推思想来优化程序的时间复杂度,且在不了解具体范围的情况下,答案也需用高精度存储,另外,也要熟练高精度多位数乘法的程序模块,做到在竞赛时能熟练使用。
离线archimedes

只看该作者 5 发表于: 2005-11-30
你是从www.oibh.org抄的!这个程序看不懂~
离线pzy
只看该作者 6 发表于: 2005-12-17
太难了

有没有简单一点的方法
离线414878523
只看该作者 7 发表于: 2006-04-20
垃圾...告诉你们!测试数据中,只要用longint长整型搞定!!!!!!!!!!!!!!!!
离线archimedes

只看该作者 8 发表于: 2006-05-09
longint搞定?不会吧,那还不简单
离线velicue
只看该作者 9 发表于: 2006-07-06
this problem is too bt
快速回复
限100 字节
 
上一个 下一个