Description
【问题描述】
一个数字被称为好数字当他满足下列条件:
它有2*n个数位,n是正整数(允许有前导0)
构成它的每个数字都在给定的数字集合S中。
- 它前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.