原题:
http://172.16.0.132/junior/#contest/show/1360/2
题目描述:
给你一个数N(1<=N<=50),每张票有2N位,同时给你这2N位上的和S,如果这张票的前N位的和等于后N位的和,那我们称这张票是吉祥的,每一位可以取0-9
你的任务是计算吉祥票的总数
输入:
输入N和S,S是所以位上的和,假设S<=1000
输出:
输出吉祥票的总数
样例输入:
2 2
样例输出:
4
分析:
题目要求组成一个2*N的数,前N位的和等于后N位的和=S/2,首先考虑两个特殊情况:N为奇数,答案为0(2)S=0和S=18*N,答案为1。
另前N的数字和为S/2的方法数=后N位数字和为S/2的方法数,所以答案等于ANS^2,ANS表示N的数字和为S/2的方法数,现在的任务就是计算ANS,很容易想到用状态f[i,j]表示i个数和为j的方法,那么ANS=f[N,S/2],怎么计算f[i,j]呢?可以从“第i上的数字是多少?”这个问题得到递推方程式:
另f[i,j]具有对称性:f[i,j]=f[i,9*i-j],可以把效率提高一倍,并要用高精度;
实现:
uses math;
var
f:array[1..50,1..450]of string;
n,s,i,j,k:longint;
function jia(x,y:string):string;
var
s:string;
i,j:longint;
a,b,c:array[0..256]of longint;
begin
fillchar(a,sizeof(a),0);
fillchar(b,sizeof(b),0);
fillchar(c,sizeof(c),0);
s:='';
a[0]:=length(x);
b[0]:=length(y);
for i:=1 to a[0]do a[i]:=ord(x[a[0]-i+1])-48;
for i:=1 to b[0]do b[i]:=ord(y[b[0]-i+1])-48;
if a[0]>b[0] then
begin
for i:=1 to a[0]do
begin
c[i]:=a[i]+b[i]+c[i];
c[i+1]:=c[i] div 10;
c[i]:=c[i] mod 10;
end;
c[0]:=a[0];
if c[a[0]+1]<>0 then inc(c[0]);
end
else
begin
for i:=1 to b[0]do
begin
c[i]:=a[i]+b[i]+c[i];
c[i+1]:=c[i] div 10;
c[i]:=c[i] mod 10;
end;
c[0]:=b[0];
if c[b[0]+1]<>0 then inc(c[0]);
end;
for i:=1 to c[0]do s:=s+chr(c[c[0]-i+1]+48);
exit(s);
end;
function cheng(x,y:string):string;
var
s:string;
i,j,t:longint;
a,b,c:array[0..256]of longint;
begin
fillchar(a,sizeof(a),0);
fillchar(b,sizeof(b),0);
fillchar(c,sizeof(c),0);
a[0]:=length(x);
b[0]:=length(y);
s:='';
for i:=1 to a[0]do a[i]:=ord(x[a[0]-i+1])-48;
for i:=1 to b[0]do b[i]:=ord(y[b[0]-i+1])-48;
for i:=1 to a[0]do
begin
t:=0;
for j:=1 to b[0]do
begin
c[i+j-1]:=t+a[i]*b[j]+c[i+j-1];
t:=c[i+j-1]div 10;
c[i+j-1]:=c[i+j-1]mod 10;
end;
c[i+j]:=t;
end;
c[0]:=a[0]+b[0];
if c[a[0]+b[0]]=0 then dec(c[0]);
for i:=1 to c[0]do s:=s+chr(c[c[0]-i+1]+48);
exit(s);
end;
begin
assign(input,'tickets.in');reset(input);
assign(output,'tickets.out');rewrite(output);
readln(n,s);
s:=s div 2;
for i:=1 to n do f[i,0]:='1';
for i:=1 to 50 do
for j:=1 to 450 do f[i,j]:='0';
for i:=1 to n do
for j:=0 to s do
begin
if j>9*i then f[i,j]:='0'
else
if(i=1)and(j>=0)and(j<=9)then f[i,j]:='1'
else
for k:=0 to min(9,j)dof[i,j]:=jia(f[i,j],f[i-1,j-k]);
end;
if(s=n*9)or(s=0)then writeln(1)
else writeln(cheng(f[n,s],f[n,s]));
close(input);close(output);
end.