您的位置:首页 > 其它

2017.1.12【初中部 】普及组模拟赛C组 幸运票 题解

2017-01-13 18:49 246 查看

原题:

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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: