• 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;
    } 
    
  • 相关阅读:
    Python find() 方法
    enumerate函数
    【Unity】项目工程源码
    【Unity】UGUI聊天消息气泡 随文本内容自适应
    Unity读Excel 输出PC端(Windows)后不能读取的问题
    【C#】读取Excel中嵌套的Json对象,Json带斜杠的问题(其三)
    【C#】读取Excel中嵌套的Json对象,Json带斜杠的问题(其二)
    【C#】读取Excel中嵌套的Json对象,Json带斜杠的问题(其一)
    Unity输出PC端(Windows) 拖拽文件到app中
    Android Studio报错Error:Failed to open zip file. Gradle's dependency cache may be corrupt
  • 原文地址:https://www.cnblogs.com/dixiao/p/15029597.html
Copyright © 2020-2023  润新知