2019.3.8 提高B组 T3 JZOJ 3056 数学

104 篇文章 0 订阅
D e s c i r p t i o n Descirption Descirption

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

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

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

    1. 它前n位之和与后n位之和相等或者它奇数位之和与偶数位之和相等

    例如对于n=2,S={1,2},合法的好数字有1111,1122,1212,1221,2112,2121,2211,2222这样8种。

已知 n n n,求合法的好数字的个数 m o d 999983 mod 999983 mod999983

数据范围: n ≤ 1000 n\leq 1000 n1000


S o l u t i o n Solution Solution

首先如果只用 ∣ S ∣ |S| S这个集合中的数时,前 n n n位之和与后 n n n位之和相等的数量是等于它奇数位之和与偶数位之和相等

自然而然想到了相乘

根据荣斥定理,我们只需要减去两个都满足的就可以我靠( w o r k   o u t work\ out work out)了

递推方程: f [ i ] [ j ] = ∑ f [ i − 1 ] [ j − a [ k ] ] f[i][j]=\sum f[i-1][j-a[k]] f[i][j]=f[i1][ja[k]]

时间复杂度: O ( 9 n 2 ) O(9n^2) O(9n2)


C o d e Code Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define WYC 999983
using namespace std;int n,a[10],m;
char s[10];
long long f[1010][9010];
long long S(int x)
{
	long long ans=0;
	for(register int i=0;i<=x*9;i++) if(f[x][i]) (ans+=f[x][i]*f[x][i]%WYC)%WYC;
	return ans;
}
signed main()
{
	scanf("%d\n",&n);
	scanf("%s",s);
	m=strlen(s);
	for(register int i=0;i<m;i++) a[i]=s[i]-48;
	f[0][0]=1;
	for(register int i=0;i<=n;i++)
	 for(register int j=0;j<=9*n;j++)
	  if(f[i][j])
	   for(register int k=0;k<m;k++)
	    (f[i+1][j+a[k]]+=f[i][j])%=WYC;
	printf("%lld",(2*S(n)%WYC-S(n/2)*S(n-n/2)%WYC+WYC)%WYC);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值