Bzoj 1236 SPOJ1433 KPSUM

来源:互联网 发布:mac 多屏幕切换快捷键 编辑:程序博客网 时间:2024/06/04 19:03

原题网址:http://www.lydsy.com/JudgeOnline/problem.php?id=1236

Time Limit: 1 Sec Memory Limit: 162 MB
Description
给你一个正整数N,依次把1到N写下来,在每两个数字之间交替的加上+,-号(注意是数字不是数),求这个表达式的值。例如,N=15时,表达式为1-2+3-4+5-6+7-8+9-1+0-1+1-1+2-1+3-1+4-1+5
Input
一个正整数N。
Output
表达式的值。
Sample Input
15
Sample Output
14
数据范围:
30%的数据中,N<=100。
100%的数据中,N<=10^15

这是道典型的数位dp题。

首先由于m位数(m≠1)的个数都是偶数个,所以第一个m位数开头都是负号。

对于奇数位数的数,2k和2k+1这两个数各位数和为1(前面的位相消,个位和为1),如:
-1+3-4
+1-3+5
对于偶数位数的数,会出现连续一段的同一位不仅数字相同,符号也相同。

对于一个m位数的n,对于小于m位的那些数因为每一种位数的数对应性质不同,而且都是满的,没有零头,可以拿出来单独处理。
剩下的那些m位数若是奇数位数,可由上面性质直接算出答案;若是偶数位数,则利用上面的性质自高位向低位统计答案,对于每一位,先算出整的部分,再算出零的部分当前位的贡献,就化归为规模更小的子问题了。

var  f:array[0..20,0..9] of int64;  c,d:array[0..20] of int64;  n,m,x,ans,s,k:int64;  i,j,l:longint;begin  readln(n);  if n<=9 then    begin      ans:=0;      for i:=1 to n do        if i and 1=1          then inc(ans,i)          else dec(ans,i);      writeln(ans);      halt;    end;  ans:=5;  x:=n;m:=0;  while x>0 do    begin      inc(m);      d[m]:=x mod 10;      x:=x div 10;    end;  c[1]:=1;  for i:=2 to m do    c[i]:=c[i-1]*10;  for i:=0 to 9 do    f[1][i]:=i;  for i:=2 to m do  //f[i][j]表示i位开头为j的数的数字和(方便起见,符号为+)    for j:=0 to 9 do      begin        f[i][j]:=c[i]*j;        for l:=0 to 9 do          dec(f[i][j],f[i-1][l]);      end;  for i:=2 to m-1 do //统计小于m位的答案    if i and 1=1      then inc(ans,c[i]*9 div 2)      else        begin          for j:=1 to 9 do            dec(ans,f[i][j]);        end;  if m and 1=1 //统计m位的答案    then      begin        inc(ans,(n-c[m]+1) div 2); //若是奇数位数直接算出答案        if n and 1=0 then          for i:=m downto 1 do            if i and 1=0              then inc(ans,d[i])              else dec(ans,d[i]);      end    else      begin        k:=-1;        for i:=m downto 1 do          begin            if i=m then s:=1 else s:=0;            for j:=s to d[i]-1 do              inc(ans,k*f[i][j]); //整的部分的答案            inc(ans,k*(n-d[i]*c[i]+1)*d[i]); //零的部分当前位的贡献            n:=n-d[i]*c[i]; //化归为子问题            k:=-k;          end;      end;  writeln(ans);end.
0 0
原创粉丝点击