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.
相关文章推荐
- 2017.1.12【初中部 】普及组模拟赛C组 连续自然数和 题解
- 2017.1.12【初中部 】普及组模拟赛C组 简单游戏 题解
- 2017.1.12【初中部 】普及组模拟赛C组 抄书 题解
- 初中OJ1997【2015.8.3普及组模拟赛】WZK打雪仗(war)
- 2016.09.17【初中部 NOIP普及组 】模拟赛
- 2016.10.05【初中部 NOIP普及组 】模拟赛总结
- 2017.1.13【初中部 】普及组模拟赛C组 excel 电子表格 题解
- 2016.09.03 初中部 NOIP普及组 模拟赛
- 初中OJ1994【普及组模拟赛】小口口矩阵
- 2016.5.28【初中部 NOIP普及组 】模拟赛总结
- 2016.11.12【初中部 NOIP普及组 】模拟赛
- 2017.1.15【初中部 】普及组模拟赛C组 小x的数列 题解
- 2017.1.18【初中部 】普及组模拟赛C组 最佳裁判 题解
- 2017.1.15【初中部 】普及组模拟赛C组 小x的极限 题解
- 2017.1.16【初中部 】普及组模拟赛C组 chicken 题解
- 2017.1.18【初中部 】普及组模拟赛C组 临时工计划 题解
- 2017.1.13【初中部 】普及组模拟赛C组 tictac 立体井字棋 题解
- 2017.1.16【初中部 】普及组模拟赛C组 match 题解
- 2017.1.18【初中部 】普及组模拟赛C组 捉迷藏 题解
- 2017.1.20【初中部 】普及组模拟赛C组 鸡腿の树荫 题解