数字

Description

【问题描述】

一个数字被称为好数字当他满足下列条件:
  1. 它有2*n个数位,n是正整数(允许有前导0)

  2. 构成它的每个数字都在给定的数字集合S中。

    1. 它前n位之和与后n位之和相等或者它奇数位之和与偶数位之和相等

    例如对于n=2,S={1,2},合法的好数字有1111,1122,1212,1221,2112,2121,2211,2222这样8种。

已知n,求合法的好数字的个数mod 999983。

Input

第一行一个数n。


接下来一个长度不超过10的字符串,表示给定的数字集合。

Output

一行一个数字表示合法的好数字的个数mod 999983。

Sample Input
2
0987654321

Sample Output
1240

Data Constraint

Hint
对于20%的数据,n≤7。
对于100%的.据,n≤1000,|S|≤10。
.
.
.
.
.
.

分析

首先我们设递推数组fi,j表示用i个数字加起来能达到j的方案数
预处理:f0,0=1
然后我们可以得出递推式为:
fi,j=∑fi-1,j-a[k](k=1~n并j-a[k]>=0)% 999983
(提示,j最大值为i*ak中最大值,但作者偷懒直接用9。反正都一样啦,至于为什么自己思考一下)
然后,我们可以发现,由于是2n的序列,所以前n位与后n位相等和奇数位与偶数位相等的方案数是一样的,所以乘2即可
方案总数为2*∑fn,i*fn,i(i=0~n*9)

我们可以很轻易地发现前n位与后n位相等的时候,有一些情况会和奇数位与偶数位相等的方案重叠
所以我们要减掉一些
减掉什么呢?
我们发现,上面的情况就相当于前n位的奇偶数位相等和后n位的奇偶数位相等
所以式子是:
(接下来l1表示n中的奇数个数,l2表示n中的偶数个数)
(∑fl1,i(i=0~l1*9)∑fl2,i(i=0~l2*9))(∑fl1,i(i=0~l1*9)*∑fl2,i(i=0~l2*9))
然后乘法分配律得
∑fl1,i(i=0~l1*9)²∑fl2,i(i=0~l2*9)²
然后之前的值减去这个时,可能为负数(因为求余,并不是算法特判),所以要加999983后模999983。
.
.
.
.
.
.

程序:
const
mo=999983;
var
n,i,j,k,l,l1,l2:longint;
s:string;
a:array[0..10]of longint;
ans1,ans2,ans:int64;
f:array[0..1001,0..9001]of int64;

begin
    readln(n);
    readln(s);
    l:=length(s);
    for i:=1 to l do
    a[i]:=ord(s[i])-ord('0');
    f[0,0]:=1;
    for i:=1 to n do
    for j:=0 to i*9 do
    for k:=1 to l do
    if (j-a[k]>=0) then f[i,j]:=(f[i,j]+f[i-1,j-a[k]]) mod mo;
    for i:=0 to n*9 do
    ans:=(ans+2*f[n,i]*f[n,i]) mod mo;
    l1:=(n+1) div 2;
    l2:=n div 2;
    for i:=0 to l1*9 do
    ans1:=(ans1+f[l1,i]*f[l1,i] mod mo) mod mo;
    for i:=0 to l2*9 do
    ans2:=(ans2+f[l2,i]*f[l2,i] mod mo) mod mo;
    ans:=(ans-ans1*ans2 mod mo +mo) mod mo;
    write(ans);
end.
posted @ 2018-03-14 16:51  银叶草  阅读(229)  评论(0编辑  收藏  举报
Live2D