内容目录
数字
(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; }