D. Destroy the Colony (Backpack Return)

original link - http://codeforces.com/contest/1111/problem/D

Title:

Give a string and select two characters at a time. Ask how many kinds of strings satisfy:

  1. It can be obtained by exchanging two characters at any time from the original string.
  2. The selected characters (two or one) appear only on one side at the same time.
  3. Other characters appear only on one side.

Analysis:

Assuming that the selected characters are on the left (the same situation on the right, and then multiplied by two), consider the different situations of the two characters.

So in the backpack without a a a, it is feasible to return the siz siz of B B B and the final dp[len/2_siz[a]siz[b]]dp[len/2-siz[a]-siz[b]]dp[len/2_siz[a]siz[b].

Each scheme is only a combination now, if it is arranged, we find that each combination has fixed len2! Len2! Siz [i]! dfrac { frac {len} {2}! frac {len} {2}! {siz [i]!} siz [i]! 2len!

Code:

/*
 *  Author : Jk_Chen
 *    Date : 2019-09-16-15.03.32
 */
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
#define debug(x) cerr<<#x<<" = "<<x<<'\n';
const LL mod=1e9+7;
const int maxn=1e5+9;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
    while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans; return ans;
}
/*_________________________________________________________begin*/
LL Pow(LL a,LL b,LL mod){
    LL res=1;
    while(b>0){
        if(b&1)res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
LL fac[maxn],ifac[maxn];
/*_________________________________________________________Pow*/
char x[maxn];
int ct[100];
int id(char c){
    if(islower(c))return c-'a';
    return c-'A'+26;
}
LL dp[52][maxn/2];
LL ans[52][52];
LL tmp[maxn/2];

int main(){
    fac[0]=1;
    rep(i,1,maxn-1)fac[i]=fac[i-1]*i%mod;
    ifac[maxn-1]=Pow(fac[maxn-1],mod-2,mod);
    per(i,maxn-2,0)ifac[i]=ifac[i+1]*(i+1)%mod;

    gets(x+1);
    int len=strlen(x+1);
    rep(i,1,len){
        ct[id(x[i])]++;
    }
    rep(i,0,51)dp[i][0]=1;
    rep(i,0,51){
        if(!ct[i])continue;
        rep(j,0,51){
            if(i==j||!ct[j])continue;
            per(k,len/2,ct[i]){
                dp[j][k]=(dp[j][k]+dp[j][k-ct[i]])%mod;
            }
        }
    }
    rep(i,0,51)
        if(ct[i]&&ct[i]<=len/2)
            ans[i][i]=dp[i][len/2-ct[i]];
    rep(i,0,50){
        if(ct[i]==0)continue;
        rep(j,i+1,51){
            if(ct[j]==0)continue;
            if(ct[i]+ct[j]>len/2)continue;
            if(i==2&&j==3){
                i=2;
            }
            rep(k,0,len/2)tmp[k]=dp[i][k];
            rep(k,ct[j],len/2){
                tmp[k]=(tmp[k]+mod-tmp[k-ct[j]])%mod;
            }
            ans[i][j]=tmp[len/2-ct[i]-ct[j]];
        }
    }
    int t=rd();
    LL mul=2ll*fac[len/2]*fac[len/2]%mod;
    rep(i,0,51){
        mul=mul*ifac[ct[i]]%mod;
    }
    while(t--){
        int l=rd(),r=rd();
        l=id(x[l]),r=id(x[r]);
        if(l>r)swap(l,r);
        printf("%lld\n",ans[l][r]*mul%mod);
    }

    return 0;
}

Posted by kernelgpf on Wed, 02 Oct 2019 16:08:58 -0700