bzoj1236

其实这道题目不难,主要要求我们有一个清晰地思路
首先可以按位数讨论,这里我把1~9单独讨论了
因为除了1位数,每个位数开头的数的开头数字1前面都是-号
然后考虑位数的奇偶性
当位数为奇数的时候比较简单
举个例子
-1+0-0
+1-0+1
-1+0-2
+1-0+3
不难发现,奇位数从开头的数开始,相邻两个数数字和都是1,这就非常好统计了
如果位数为偶数,则这位数的一个数排完之后,下一个数的开头符号还是上一个数的开头符号
就是-1+0 -1+1 -1+2……这个意思
于是我们就要数位dp来处理

 1 var f:array[0..20,0..10] of int64;
 2     d,c:array[0..20] of int64;
 3     ans,x,n:int64;
 4     s,i,m,j,k,t:longint;
 5 
 6 begin
 7   readln(n);
 8   if n<=9 then
 9   begin
10     for i:=1 to n do
11       if i mod 2=1 then ans:=ans+i else ans:=ans-i;
12     writeln(ans);
13     halt;
14   end;
15   ans:=5;
16   m:=0;
17   x:=n;
18   while x<>0 do
19   begin
20     inc(m);
21     d[m]:=x mod 10;
22     x:=x div 10;
23   end;
24   c[1]:=1;
25   for i:=2 to m do
26     c[i]:=c[i-1]*10;
27   for i:=0 to 9 do
28     f[1,i]:=i;
29   for i:=2 to m do  //开头为j,是i位数的每个数的数字和(注意这里默认每个数的开头都是+)
30     for j:=0 to 9 do
31     begin
32       f[i,j]:=c[i]*j;
33       for k:=0 to 9 do
34         f[i,j]:=f[i,j]-f[i-1,k];
35     end;
36   for i:=2 to m-1 do  //位数小于n的数字和
37   begin
38     if i mod 2=0 then
39     begin
40       for j:=1 to 9 do
41         ans:=ans-f[i,j];
42     end
43     else ans:=ans+9*c[i] div 2;
44   end;
45   if m mod 2=1 then  //n位数为奇数可以直接计算
46   begin
47     ans:=ans+(n-c[m]+1) div 2;
48     if n mod 2=0 then
49     begin
50       for i:=m downto 1 do
51         if i mod 2=0 then ans:=ans+d[i]
52         else ans:=ans-d[i];
53     end;
54   end
55   else begin
56     k:=-1;
57     for i:=m downto 1 do  //n位数为偶数逐位统计
58     begin
59       if i=m then s:=1 else s:=0;
60       for j:=s to d[i]-1 do  
61         ans:=ans+k*f[i,j];
62       ans:=ans+k*(n-d[i]*c[i]+1)*d[i];  //这里要好好琢磨
63       n:=n-d[i]*c[i];
64       k:=k*(-1);
65     end;
66   end;
67   writeln(ans);
68 end.
View Code
原文地址:https://www.cnblogs.com/phile/p/4473046.html