#include <iostream>
using namespace std;
int main()
{
int n,m,i,j,p,k;
int a[100],b[100];
cin >> n >> m;
a[0]=n;
i=0;
p=0;
k=0;
do
{
for (j=0;j<i;j++)
if (a[i]==a[j])
{
p=1;
k=j;
break;
}
if (p)
break;
b[i]=a[i]/m;
a[i+1]=a[i]%m*10;
i++;
}while (a[i]!=0);
cout << b[0] << ".";
for (j=1; j<k; j++)
cout << b[j];
if (p)
cout << "(";
for (j=k;j<i;j++)
cout << b[j];
if (p)
cout << ")";
cout << endl;
return 0;
}输入:5 13 输出:_________
这题考循环节检测。拿到题先别急着算,盯着数组a存余数、b存商那几行,明白它在模拟竖式除法;用‘余数重就停’的思路,一步步手算5÷13,就能直接写出答案。
最容易掉进两个坑:一是把a[1]当成循环起点,忽略p=1时k=j=1,导致输出格式变成0.(384615)却漏掉循环标记,或者误以为要输出0.384615384615…;二是死算到a[7]=50才反应过来循环,却忘了题目给的输出格式里,一旦检测到循环(p=1),必须在循环节前后加括号,且只输出到i-1,所以别把b[6]也打出来。
这题属于循环结构与一维数组的综合应用,命题人想考的是:能不能读懂一段模拟竖式除法的代码,并准确判断何时出现循环。这类题在NOIP提高组初赛里很常见——给一段看似复杂的循环,让你填输出或找规律。命题人喜欢在数组下标、循环条件、break的位置挖坑,比如这里p=1时k=j,意味着第一次发现重复余数时,k就指向那个重复的位置,而输出时要从k开始重复部分。如果你没注意p的作用,很容易把输出截断或多加一位。
程序里有两个数组:a用来存每次的余数,b用来存每次的商(小数位)。i是循环计数器,j用来检查当前余数a[i]之前有没有出现过。p是个标记,只要发现重复就置1,然后break跳出内层循环;k记录第一次重复出现的位置。整个逻辑就是:做除法,每算一位,把余数存起来,如果这个余数以前出现过,说明后面会重复,循环结束。