DTOJ#5208. 蓝buff一吃就起飞

传送门

马老师打算起飞。

一个长度为 2 n   ( 2n\ ( 2n (可能有前缀 0 ) 0) 0) 的非负整数 x x x g o o d good good 的,当且仅当存在两个长度为 n   ( n\ ( n (可能有前缀 0 ) 0) 0) 的非负整数 a 、 b a、b ab 满足 a + b = 1 0 n a+ b =10 ^ n a+b=10n,并且对于 0 ∼ 9 0\sim9 09 每个数位 d d d,都有 S d ( x ) = S d ( a ) + S d ( b ) ( S d ( x ) Sd(x) = Sd(a) + Sd(b)(Sd(x) Sd(x)=Sd(a)+Sd(b)(Sd(x) x x x 的十进制中 d d d 出现了多少次 ) ) )。例如 0829 0829 0829 g o o d good good 的, 98 + 02 = 100 98 + 02 = 100 98+02=100

给出一个长度为 2 n 2n 2n 的序列,其中有些位置是问号。将每个问好替换为 0 ∼ 9 0 \sim 9 09 任意一个数位后,有多少个 g o o d good good 数,答案对 1000000007 1000000007 1000000007 取模。

一行长度为 2 n 2n 2n 的字符串,由 0 ∼ 9 0 \sim 9 09 ? ? ? 构成。

一个整数表示答案。

样例输入

2?4?

样例输出

4

m m m ? ? ? 的个数。

对于 30 % 30\% 30% 的数据, n ≤ 6 n \leq 6 n6

对于另外 30 % 30\% 30% 的数据, m ≤ 6 m \leq 6 m6

对于 100 % 100\% 100% 的数据, n ≤ 50000 , m ≤ 1000 n \leq 50000,m \leq 1000 n50000,m1000

题解:
注意到,设 a a a 的十进制为 a 1 a 2 a 3 … a n a_1a_2a_3\dots a_n a1a2a3an b b b b 1 b 2 b 3 … b n b_1b_2b_3\dots b_n b1b2b3bn,那么必定是 a 1 + b 1 = 9 a_1+b_1=9 a1+b1=9, a 2 + b 2 = 9 a_2+b_2=9 a2+b2=9, a k + b k = 10 a_k+b_k=10 ak+bk=10, a k + 1 + b k + 1 = 0 … a n + b n = 0 a_{k+1}+b_{k+1}=0\dots a_n+b_n=0 ak+1+bk+1=0an+bn=0
于是考虑枚举 a k , b k a_k,b_k ak,bk,然后贪心先配已知的和为十,然后枚举和为十的数对 D P DP DP
注意考虑 0 + 9 0+9 0+9 0 + 0 0+0 0+0,当剩余的数个数是奇数时,多的位可以填 0 0 0 9 9 9 ,但填 9 9 9 时不能有 0 + 0 0+0 0+0 出现,因为会算重。

扫描二维码关注公众号,回复: 12884606 查看本文章
#include<bits/stdc++.h>
#define N 50005
#define M 1005
using namespace std;
const int mod=1000000007;
int read(){
    
    
	int op=1,sum=0;char ch=getchar();
	while(ch<'0'||ch>'9') {
    
    if(ch=='-') op=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+ch-'0',ch=getchar();
	return op*sum;
}
int jc[N],jcinv[N];
inline int power(int x,int c){
    
    
	int now=1;
	while(c){
    
    
		if(c&1)now=1ll*now*x%mod;
		x=1ll*x*x%mod;c>>=1;
	}
	return now;
}
inline void init(int n){
    
    
	jc[0]=1;
	for(int i=1;i<=n;++i)jc[i]=1ll*jc[i-1]*i%mod;
	jcinv[n]=power(jc[n],mod-2);
	for(int i=n-1;i+1;--i)jcinv[i]=1ll*jcinv[i+1]*(i+1)%mod;
}
inline int C(int x,int y){
    
    
	if(x<y||y<0)return 0;
	return 1ll*jc[x]*jcinv[y]%mod*jcinv[x-y]%mod;
}
char s[N<<1];
int cnt[11],res,pre[11],cal[11],f[M],g[M],tmp[M];
int dx[]={
    
    1,2,3,4};
int dy[]={
    
    8,7,6,5};
int main(){
    
    
 //   freopen("data.in","r",stdin);
//	freopen("eatbuff.in","r",stdin);
//	freopen("eatbuff.out","w",stdout); 
	init(M-2);
	scanf("%s",1+s);
	int n=strlen(1+s);
	for(int i=1;i<=n;++i){
    
    
		if(s[i]=='?'){
    
    ++res;continue;}
		pre[s[i]-'0']++;
	}
	int ans=0,num=res;
	for(int t=1;t<=5;++t){
    
    
		res=num;
		memset(cal,0,sizeof(cal));
		for(int j=0;j<10;++j)cnt[j]=pre[j];
		cnt[t]--,cnt[10-t]--;
		if(cnt[t]<0){
    
    
			cal[t]++;cnt[t]++;res--;
		}
		if(cnt[10-t]<0){
    
    
			cal[10-t]++;cnt[10-t]++;res--;
		}
		for(int j=0;j<=4;++j){
    
    
			int now=min(cnt[j],cnt[9-j]);
			cnt[j]-=now,cnt[9-j]-=now;
		}
		for(int j=1;j<=9;++j){
    
    
			if(cnt[j]){
    
    
			    cal[9-j]+=cnt[j],res-=cnt[j];
			}
		}
		if(res<0)continue;
		memset(tmp,0,sizeof(tmp));
		if(res&1){
    
    
			res>>=1;
			cal[0]++;
			for(int i=0;i<=res;++i){
    
    //0 0
				for(int j=0;j+i<=res;++j){
    
    //0 9
					tmp[i+j]=(tmp[i+j]+1ll*jcinv[cal[0]+2*i+j]*jcinv[cal[9]+j]%mod)%mod;
				}
			}
			cal[0]--;
			cal[9]++;
			for(int j=0;j<=res;++j){
    
    
				tmp[j]=(tmp[j]+1ll*jcinv[cal[0]+j]*jcinv[cal[9]+j]%mod)%mod;
			}
			cal[9]--;
			res=(res<<1)|1;
		}else{
    
    
			res>>=1;
			for(int i=0;i<=res;++i){
    
    //0 0
				for(int j=0;j+i<=res;++j){
    
    //0 9
					tmp[i+j]=(tmp[i+j]+1ll*jcinv[cal[0]+2*i+j]*jcinv[cal[9]+j]%mod)%mod;
				}
			}
			res<<=1;
		}
		if(res&1)cal[9]++,cnt[0]--;
		res>>=1;
		for(int i=1;2*i<=cnt[0];++i){
    
    // 9 9
		    for(int j=0;j+i<=res;++j){
    
    // 0 9
		    	tmp[i+j]=(tmp[i+j]+1ll*jcinv[cal[0]+j]*jcinv[cal[9]+2*i+j]%mod)%mod;
		    }
		}
		memset(f,0,sizeof(f));
		f[0]=1;
		for(int t=0;t<4;++t){
    
    
			memset(g,0,sizeof(g));
			for(int i=0;i<=res;++i){
    
    
				for(int j=0;j<=i;++j){
    
    
					g[i]=(g[i]+1ll*f[j]*jcinv[cal[dx[t]]+i-j]%mod*jcinv[cal[dy[t]]+i-j]%mod)%mod;
				}
			}
			for(int i=0;i<=res;++i){
    
    
				f[i]=g[i];
			}
		}
		int pre=ans;
		for(int i=0;i<=res;++i){
    
    
			ans=(ans+1ll*f[i]*tmp[res-i]%mod)%mod;
		}
	}
	ans=1ll*ans*jc[num]%mod;
	printf("%d\n",(ans+mod)%mod);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/CSDNzhanghongyu/article/details/110495261