zoukankan      html  css  js  c++  java
  • [计蒜之道复赛 2018] 贝壳找房计数比赛

    Description

    贝壳找房举办了一场计数比赛,比赛题目如下。

    给一个字符串 (s) 和字符串 (t),求出 (s) 的所有去重全排列中 (t) 出现的次数。比如aab的去重全排列为aabababaa。注意aaaa算出现两次aaa

    你的老大希望你帮他写一个程序作弊。

    Input

    第一行一个整数 (T),表示数据组数。

    每组数据中,第一行一个字符串 (s),第二行一个字符串 (t)

    数据保证 (1le T le 100), (1le |t| le |s| le 10^5), (t,s) 只包含小写字母。

    Output

    输出一共 T 行,每行一个整数,表示所求答案对 (10^9+7) 取模的结果。

    Solution

    这个去重全排列有点吓人,实际上就是可重集合的排列数嘛!

    那么我们可以枚举子串 (t) 在主串 (s) 中出现的位置,然后将 (s) 除了 (t) 剩下的部分重新排列更新答案即可。

    注意 (t)(s) 中出现的次数可以 (mathcal O(1)) 求,也就是 (n-m+1) 次。

    Code

    #include<cstdio>
    #include<cstring>
    #define N 100005
    #define int long long
    const int mod=1e9+7;
    
    int T;
    int xx[N];
    char a[N],b[N];
    int fac[N],ifac[N];
    
    int ksm(int a,int b){
    	int ans=1;
    	while(b){
    		if(b&1)
    			ans=ans*a%mod;
    		a=a*a%mod;
    		b>>=1;
    	}
    	return ans;
    }
    
    signed main(){
    	fac[0]=1;ifac[0]=1;
    	for(int i=1;i<=N-5;i++)
    		fac[i]=fac[i-1]*i%mod,ifac[i]=ksm(fac[i],mod-2);
    	scanf("%lld",&T);
    	while(T--){
    		scanf("%s%s",a,b);
    		int n=strlen(a),m=strlen(b);
    		memset(xx,0,sizeof xx);
    		for(int i=0;i<n;i++)
    			xx[a[i]-'a']++;
    		for(int i=0;i<m;i++)
    			xx[b[i]-'a']--;
    		int ans=fac[n-m];
    		for(int i=0;i<26;i++)
    			ans=ans*ifac[xx[i]]%mod;
    		ans=ans*(n-m+1)%mod;
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    二、有限状态机(FSM)
    一、同步状态机
    quartus ii 中文注释乱码解决办法
    基于FPGA的线阵CCD图像测量系统研究——笔记
    数据接口的同步方法
    Servlet和web服务器关系
    实现项目本地,测试,生产3套环境
    Tomcat--startup.bat文件
    Servlet--HttpUtils类
    Servlet--HttpSessionBindingListener接口,HttpSessionBindingEvent类
  • 原文地址:https://www.cnblogs.com/YoungNeal/p/9247080.html
Copyright © 2011-2022 走看看