ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

D. Destroy the Colony(退背包)

2019-09-16 19:37:38  阅读:252  来源: 互联网

标签:背包 int rep Colony len Destroy ct dp mod


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

题意:

给出一个字符串,每次选择两个位置的字符,问有多少种字符串满足:

  1. 可以由原字符串任意次交换两个字符后得到;
  2. 选择的字符(两个或者一个)同时只出现在一边;
  3. 其他字符只出现一边。

解析:

假设选择的字符在左边(右边的情况相同,最后乘二即可),考虑两个字符不同的情况。

那么就是在不选择aaa的背包里面,退掉bbb的sizsizsiz,最后的dp[len/2siz[a]siz[b]]dp[len/2-siz[a]-siz[b]]dp[len/2−siz[a]−siz[b]]就是可行的方案。

每个方案现在还只是组合,变为排列的话,发现每种组合固定有len2!len2!siz[i]!\dfrac{\frac{len}{2}!\frac{len}{2}!}{siz[i]!}siz[i]!2len​!2len​!​种排序。

代码:

/*
 *  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;
}

标签:背包,int,rep,Colony,len,Destroy,ct,dp,mod
来源: https://blog.csdn.net/jk_chen_acmer/article/details/100897358

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有