「NOIP模拟赛」数字
「问题描述」
一个数字被称为好数字当他满足下列条件:
- 它有2*n个数位,n是正整数(允许有前导0)。
- 构成它的每个数字都在给定的数字集合S中。
- 它前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。
题解
ANS=前n位之和与后n位之和相等的方案数+奇数位之和与偶数位之和相等的方案数-前n位之和与后n位之和相等且奇数位之和与偶数位之和相等的方案数
前2个需要+的方案数都很好求,直接递推,重点是最后一个要满足2个条件的方案数怎么求,其实也很简单:
因为前n位之和=后n位之和,奇数位之和=偶数位之和
所以前n位中奇数位之和=后n位中偶数位之和 且
前n位中偶数位之和=后n位中奇数位之和
现在只要求上面这个问题的方案数,由于两个等式中的元素无交集,也是十分好算的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<vector> #define mod 999983 #define ll long long using namespace std; inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n; char ch[15]; int a[15]; int f[1005][9005]; ll ans; ll cal(int x) { ll ans=0; for(int i=0;i<=x*9;i++) if(f[x][i]) ans=(ans+((ll)f[x][i]*f[x][i]))%mod; return ans; } int main() { //freopen("num.in","r",stdin); //freopen("num.out","w",stdout); n=read(); scanf("%s",ch); int l=strlen(ch); for(int i=0;i<l;i++) a[i+1]=ch[i]-'0'; f[0][0]=1; for(int i=0;i<n;i++) for(int j=0;j<=n*9;j++) if(f[i][j]) for(int k=1;k<=l;k++) f[i+1][j+a[k]]=(f[i+1][j+a[k]]+f[i][j])%mod; ans=2*cal(n)-cal(n/2)*cal(n-n/2); printf("%d",(ans%mod+mod)%mod); return 0; } |
请问今天的模拟赛可以公布下吗
这个是校内的模拟赛,可以联系我索要。。。但是好像在oj上不一定找得到