数字
(num.c/cpp/pas)
【问题描述】
一个数字被称为好数字当他满足下列条件:
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。
【输入格式】
第一行一个数n。
接下来一个长度不超过10的字符串,表示给定的数字集合。
【输出格式】
一行一个数字表示合法的好数字的个数mod 999983。
【样例输入】
2
0987654321
【样例输出】
1240
【数据规模】
对于20%的数据,n≤7。
对于100%的.据,n≤1000,|S|≤10。
这题难点在求前n位之和与后n位之和相等与它奇数位之和与偶数位之和相等的交集
……
记得第一个数一定要(long long ) c++中对 3000这样的常量都是算int的,而等号优先级最低
另外本题是乘法原理+加法原理
先用乘法原理 求出 A=x a=y B=y b=x 的方案数 记得%F
然后将所有的情况相加++
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<cctype>
#include<functional>
#include<algorithm>
#include<iostream>
using namespace std;
#define F (999983)
#define MAXN (1000+10)
#define MAXM (10000+10)
int n,m;
char s[100];
int a[100],siz=0;
int f[MAXN][MAXM];
int main()
{
freopen("num.in","r",stdin);
freopen("num.out","w",stdout);
scanf("%d",&n);
scanf("%s",s);
memset(f,0,sizeof(f));
for (int i=0;i<strlen(s);i++)
a[++siz]=s[i]-'0';
// for (int i=1;i<=siz;i++) cout<<a[i]<<' ';
sort(a+1,a+1+siz);
for (int i=1;i<=siz;i++)
{
f[1][a[i]]=1;
// cout<<a[i]<<' ';
}
f[0][0]=1;
for (int i=2;i<=n;i++)
for (int j=i*a[1];j<=i*a[siz];j++)
{
/* if (j==18)
{
cout<<'s';
}
*/ for (int k=1;k<=siz;k++)
if (j-a[k]>=0)
f[i][j]=(f[i][j]+(f[i-1][j-a[k]])%F)%F;
}
long long ans=0;
for (int j=0;j<=n*a[siz];j++)
{
// if (f[n][j]>0) cout<<j<<' '<<f[n][j]<<endl;
ans=ans+(long long)(f[n][j])*(long long)(f[n][j]);
ans%=F;
}
// cout<<(2*ans)%F<<endl;
/*现在开始几算相同的情况
A 前奇 B 前偶 a 后奇 b 后偶
显然 A+a=B+b A+a=B+b ->A=b&&sa=B
则答案为
∑(a*A*b*B) 这4个数为(此处a,A,b,B指当它们正好等于这个值的方案数
∑ (a^2*A^2)
∑ (f[n/2.i]^2*f[n/2+n%2,i])
*/
// cout<<ans<<endl;
long long tmpA=0;
for (int i=(n/2)*a[1];i<=(n/2)*a[siz];i++)
tmpA=(tmpA+(long long)f[n/2][i]*f[n/2][i])%F;
long long tmpB=0;
for (int i=(n/2+n%2)*a[1];i<=(n/2+n%2)*a[siz];i++)
tmpB=(tmpB+(long long)f[n/2+n%2][i]*f[n/2+n%2][i])%F;
// cout<<tmpA<<' '<<tmpB;
// cout<<tmpA*tmpB<<endl;
ans=(ans*2)%F;
// cout<<ans<<endl;
{
// cout<<ans<<' '<<tmpA*tmpB;
}
ans=(ans-tmpA*tmpB+F*((tmpA*tmpB)/F)+F)%F;
cout<<ans<<endl;
// while(1);
return 0;
}