zoukankan      html  css  js  c++  java
  • CF1111D Destroy the Colony

    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;
    } 
    
  • 相关阅读:
    gmap4rails
    gmap4rails
    devise的使用的中文教程
    对每个 IP 访问量实时监控。
    下载文件总结
    安装Wamp后 Apache无法启动的解决方法
    CSS,fontfamily,好看常用的中文字体
    TP框架下载功能  不想下天桥  博客园
    用PHP,怎么获取PHP.ini中的文件上传最大的字节数。也就是默认的2M
    这个技术wiki的内容很不错
  • 原文地址:https://www.cnblogs.com/dixiao/p/15029597.html
Copyright © 2011-2022 走看看