• 895D


    给你串a串b,问用a的排列生成新串c满足字典序a<c<b的串c种类数

    问题转化成问f(s),表示用已有字符构建的字符串字典序上小于s,答案就是f(b)-f(a)-1

    这样一转化就不用枚举两个字典序变化点了。。

    然后i枚举字典序变化点,j枚举字符集

    由于字典序变化点越靠后贡献越小,所以维护一个cur表示当前可用字符生成的不同字符串个数,

    每当决定一个字符,cur就要除掉剩下字符的个数,再乘上这个要用的字符的剩余个数

    #include<bits/stdc++.h>  
    //#pragma comment(linker, "/STACK:1024000000,1024000000")   
    #include<stdio.h>  
    #include<algorithm>  
    #include<queue>  
    #include<string.h>  
    #include<iostream>  
    #include<math.h>  
    #include<set>  
    #include<map>  
    #include<vector>  
    #include<iomanip>  
    using namespace std;  
    #define ll long long  
    #define pb push_back  
    #define FOR(a) for(int i=1;i<=a;i++) 
    #define sqr(a) (a)*(a)
    
    const int inf=0x3f3f3f3f;
    const int maxn=1e6+5;
    const int mod=1e9+7;
    
    int n;
    char a[maxn],b[maxn];
    int cnt[26],c[26];
    int fac[maxn],rfac[maxn],save_rev[maxn];
    
    int f(char *s){
    	memcpy(c,cnt,sizeof c);
    	int cur=fac[n];
    	for(int i=0;i<26;i++){
    		if(c[i])
    			cur=1ll*cur*rfac[c[i]]%mod;
    	}
    	//cur是剩下字符可构成字符串种数
    	int ans=0;
    	for(int i=1;i<=n;i++){	//枚举不同位置
    		for(int x=0;x<s[i]-'a';x++){
    			if(c[x]){		//枚举比他小的字符
    				int now=cur;
    				now=1ll*now*save_rev[n-i+1]%mod;	//选定一种字符
    				now=1ll*now*c[x]%mod;				//选哪一个
    				ans=(ans+now)%mod;
    			}
    		}
    		if(c[s[i]-'a']){
    			cur=1ll*cur*save_rev[n-i+1]%mod;
    			cur=1ll*cur*c[s[i]-'a']%mod;
    			c[s[i]-'a']--;
    		}else{
    			break;
    		}
    	}
    	return ans;
    }
    
    int rev(int a){
    	int ret=1;
    	for(int b=mod-2;b;b>>=1,a=(ll)a*a%mod)
    		if(b&1)
    			ret=(ll)ret*a%mod;
    	return ret;
    }
    
    int main(){
    	fac[0]=rfac[0]=1;
    	for(int i=1;i<maxn;i++){
    		fac[i]=(ll)i*fac[i-1]%mod;
    		save_rev[i]=rev(i);
    		rfac[i]=(ll)save_rev[i]*rfac[i-1]%mod;
    	}
    	scanf("%s%s",a+1,b+1);
    	n=strlen(a+1);
    	for(int i=1;i<=n;i++){cnt[a[i]-'a']++;}
    	printf("%d
    ",(f(b)-f(a)-1+mod)%mod);
    }


  • 相关阅读:
    fedora安装后的配置
    linux下的Shell编程(7)使用-x和-n调试shell程序
    linux下的Shell编程(8)自定义函数
    linux下的Shell编程(6)case和select
    linux下的Shell编程(5)循环
    linux下的Shell编程(4)特殊的变量和占位符
    linux下的Shell编程(3)shell里的流程控制
    Linux下的Shell编程(2)环境变量和局部变量
    Linux下的Shell编程(1)最简单的例子
    Docker学习笔记
  • 原文地址:https://www.cnblogs.com/Drenight/p/8611206.html
Copyright © 2020-2023  润新知