• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

CF1111D Destroy the Colony

开发技术 开发技术 7小时前 2次浏览

CF1111D Destroy the Colony

考虑到排列数只和颜色有关。

那么根据多重集排列公式:

(ans = frac{n!}{r1!r2!….rn!})

(m = frac{n}{2}),我们知道一种拼凑方式的排列答案为frac{m!}{(a1!….an!)} * frac{m!}{(b1!….bn!)}

那么我们只要计算怎么用(k_1,k_2,k_3到k_n)这些长度拼凑出(m)就好

那么是一个典型的(01背包问题)

考虑有两种颜色要在同一边的限制,那么做一个退背包,再把两种颜色合在一起当新物品就好。

复杂度(O(|E|^2n + q))

// Problem: CF1111D Destroy the Colony
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF1111D
// Memory Limit: 500 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long 
#define N 100010
#define mod 1000000007
#define QWQ QAQ

ll a[N],f[N],fac[N],inv[N],mul;
ll n,m,q,cnt[53],ans[53][53];
char ch[N];

int char_to_int(char x) {
	if(x >= 'a' && x <= 'z') return x-'a';
	return x-'A'+26;
}

inline ll pow(ll a,ll b){
	ll ans = 1;
	while(b){
		if(b & 1)ans = a * ans % mod;
		a = a * a % mod;
		b >>= 1;
	}
	return ans;
}

inline void add(int x){
	if(x == 0)return ;
	for(int i = m;i >= x;--i)f[i] = (f[i] + f[i - x] > mod ? f[i] + f[i - x] - mod : f[i] + f[i - x]);
}

inline void del(int x){
	if(x == 0)return;
	for(int i = x;i <= m;++i)f[i] = (f[i] - f[i - x] + mod > mod ? f[i] - f[i - x] : f[i] - f[i - x] + mod);
}

inline ll read(){
	ll ans = 0;
	char a = getchar();
	while(!(a <= '9' && a >= '0'))
	a = getchar();
	while(a <= '9' && a >= '0')
	ans = (ans << 3) + (ans << 1) + (a - '0'),a = getchar();
	return ans;
}

int main(){
	scanf("%s",ch + 1);
	n = std::strlen(ch + 1);
	m = n / 2;
	fac[0] = 1;
	for(int i = 1;i <= n;++i)
	fac[i] = fac[i - 1] * i % mod;
	inv[n] = pow(fac[n],mod - 2);
	mul = fac[m] * fac[m] % mod;
	for(int i = n - 1;i >= 0;--i)
	inv[i] = inv[i + 1] * (i + 1) % mod;
	for(int i = 1;i <= n;++i)
	a[i] = char_to_int(ch[i]),cnt[a[i]] ++ ;
	f[0] = 1;
	for(int i = 0;i < 52;++i){
		add(cnt[i]);
		mul = mul * inv[cnt[i]] % mod;
	}
	for(int i = 0;i < 52;++i)ans[i][i] = f[m];
	for(int i = 0;i < 52;++i)
	for(int j = i + 1;j < 52;++j){
		del(cnt[i]),del(cnt[j]);
		add(cnt[i] + cnt[j]);
		ans[i][j] = ans[j][i] = f[m];
		del(cnt[i] + cnt[j]);
		add(cnt[i]),add(cnt[j]);
	}
	q = read();
	while(q -- ){
		ll x,y;
		x = read(),y = read();
		std::cout<<ans[a[x]][a[y]] * mul % mod<<std::endl;
	}
	return 0;
} 

程序员灯塔
转载请注明原文链接:CF1111D Destroy the Colony
喜欢 (0)