JZOJ 3056. 【NOIP2012模拟10.27】数字

题目

Description

【问题描述】


    一个数字被称为好数字当他满足下列条件:


1. 它有2*n个数位,n是正整数(允许有前导0)   


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


    3. 它前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。

 

分析

  •  答案其实是

  •  前n位之和与后n位之和相等+它奇数位之和与偶数位之和相等-两个都有的
  •  前两种很好求,递推就好了
  •  第三种其实就是 

     因为前n位之和=后n位之和,奇数位之和=偶数位之和

     所以前n位中奇数位之和=后n位中偶数位之和 且

     前n位中偶数位之和=后n位中奇数位之和

 

代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<vector>
 8 #define mod 999983
 9 #define ll long long
10 using namespace std;
11 inline ll read()
12 {
13     ll x=0,f=1;char ch=getchar();
14     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
15     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
16     return x*f;
17 }
18 int n;
19 char ch[15];
20 int a[15];
21 int f[1005][9005];
22 ll ans;
23 ll cal(int x)
24 {
25     ll ans=0;
26     for(int i=0;i<=x*9;i++)
27         if(f[x][i])
28             ans=(ans+((ll)f[x][i]*f[x][i]))%mod;
29     return ans;
30 }
31 int main()
32 {
33     n=read();
34     scanf("%s",ch);
35     int l=strlen(ch);
36     for(int i=0;i<l;i++)
37         a[i+1]=ch[i]-'0';
38     f[0][0]=1;
39     for(int i=0;i<n;i++)
40         for(int j=0;j<=n*9;j++)
41             if(f[i][j])
42                 for(int k=1;k<=l;k++)
43                     f[i+1][j+a[k]]=(f[i+1][j+a[k]]+f[i][j])%mod;
44     ans=2*cal(n)-cal(n/2)*cal(n-n/2);
45     printf("%d",(ans%mod+mod)%mod);
46     return 0;
47 }

猜你喜欢

转载自www.cnblogs.com/zjzjzj/p/10500574.html