清华 2012 求1和2的个数

来源:互联网 发布:c语言中的float 编辑:程序博客网 时间:2024/06/13 11:42

题目:

输入正整数N1=<N<=10^100(10100次方)),输出F(N) mod20123F(N)表示小于等于N的自然数中12的个数之和。例如:1,2,3,4,5,6,7,8,9,10,11序列中12的个数之和为5,因此F(11)=5


思路:

Nstring存储,先求出F(N[0]),再求出F(N[0]N[1]),再求出F(N[0]N[1]N[2])……,最后求出F(N)。而由前一个F求出后一个F’,用公式:F’=(F-cons)*10+ cons*(newChar+1) + preNum*2 + min(newChar,2) 假设由F(N[0]…N[i])F(N[0]…N[i]N[i+1]),例如由F(52)F(526):

  • F:                  F(N[0]…N[i])                                              F(52)
  • F’:                  F(N[0]N[i]N[i+1])                                  F(526)   
  • cons:              N[0]—N[i]12的个数。                           1
  • preNum:       N[0]…N[i]这个数字字符串组成的数字。   52
  • newChar:     新的那个数字符号,即N[i+1]                  6

 

公式分为4部分:

  1. (F-cons)*10 :               F(52)中的数(1,2,10,11,…,29,31,32,41,42,51),变成F(526)后,都会依次和0~9组合(10~19,20~29,100~109,…,510~519),所以乘以10。又因为preNum本身不一定能组成preNum0~9,所以交给第二项来单独算(52只能算520~526)
  2. cons*(newChar+1):  见上。
  3. preNum*2 :                F(526)中,个位数也新增加了12,为每10个数中,就必有两个数的个位为12。而526共有preNum(52)个整10(0~519),所以用preNum*2。至于520~526个位数有几个12,要交给第四项单独计算。
  4. min(newChar,2):      见上。

过程:
1.在使用"?:"时,若运算符若非直接赋值,要括号括起来。因为其优先级很低。如:cons=cons+((newChar==1||newChar==2)?1:0);   
   不可cons=cons+(newChar==1||newChar==2)?1:0; 否则会先算加号。      

#include <iostream>#include <stdio.h>#include <string>using namespace std;int min(int a,int b){return a<b?a:b;}int main(){string N;int len,i;int F,preNum,cons,newChar;while(cin>>N){len=N.length();F=cons=preNum=newChar=0;for(i=0;i<len;i++){                                //由F(N[0])求到F(N[0]N[1]...N[len-1])newChar=N[i]-48;F=(F-cons)*10 + cons*(newChar+1) + preNum*2 + min(newChar,2);//套公式计算preNum=(preNum*10+newChar)%20123;cons=cons+((newChar==1||newChar==2)?1:0);                       //?:运算符若非直接赋值,要括号括起来。因为其优先级很低。F=F%20123;}printf("%d\n",F);                                  //输出结果}return 0;}

1 0
原创粉丝点击