您的位置:首页 > 其它

九度OJ 1491 清华大学2012机试 《求1和2的个数》

2015-02-09 17:22 183 查看
给定正整数N,函数F(N)表示小于等于N的自然数中1和2的个数之和,例如:1,2,3,4,5,6,7,8,9,10序列中1和2的个数之和为3,因此F(10)=3。输入N,求F(N)的值,1=<N<=10^100(10的100次方)若F(N)很大,则求F(N)mod20123的值。

输入:

输入包含多组测试数据,每组仅输入一个整数N。

输出:

对于每组测试数据,输出小于等于N的自然数中1和2的个数之和,且对20123取模。

样例输入:

10

11

样例输出:

3

5

看了一份别人的代码,十分简略,不明白怎么做的,就发到了论坛里,有人给讲解了,讲得很棒

比如输入12345,那么先算F(1),再由F(1)算出F(12),依次再算出F(123),F(1234),F(12345);

主要计算的就是rslt=(rslt-cnt)*10+num*2+cnt*(t+1)+min(t,2);这一句了。

rslt是结果;num是实际输入的数;cnt是num这个数中1,2的数量;

首先认为已经算出了F(12)=rslt,需要算F(123)

1.显然12变成了12X的形式,所以原来1-11中每一个数都可以加上一个个位(因为不知道个位是不是9,所以最后一个12不能乘10,以后单独计算),而个位是从0-9,所以原来的每个数都有10中变化,而最后一个数12的1,2的数量为cnt,所以有(rslt-cnt)*10,;

(比如比12小的有1,2的数是:1,2,10,11,扩大十倍后,有10-19,20-29,100-109,110-119,每个数各对应十个数,他们原本的的1和2被加了十次,所以乘以10)

2.上一步中余有一个12没有计算,显然12X这个数的个位只能是0-3,所以有cnt*(t+1);

(t是X位的数,cnt是12的1,2个数,为2,t从0开始,所以是cnt*(t+1)个)

3.上面的计算中都没有考虑对个位为1,2的计数,00-11中个位为1,2的显然是每10个数中有2个,所以有num*2

4.12X个位的1,2个数,直接判断就好了,min(t,2);

#include <stdio h="">
#include <string h="">
#include <iostream>
using namespace std;

int main()
{
char N[110] = {0};
while(cin>>N)
{
int i,t = 0;
int result,num,cnt;
//result是结果,num是当前计算的N,cnt即num这个数中的1,2个数
result = num = cnt = 0;
int len = strlen(N);
for(i = 0; i < len; i++)
{
t = N[i] - '0';
result = (result - cnt)*10 + cnt*(t+1) + num*2 + min(t,2);
num = num*10 + t;

if(t == 1 || t == 2)
cnt++;
num %= 20123;
result %= 20123;
}
printf("%d\n",result);
}
return 0;
}
</iostream></string></stdio>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: