Codeforces 895D Round#448 2D :组合数学+小学数学优化
来源:互联网 发布:边缘端口防环路 编辑:程序博客网 时间:2024/05/16 10:52
题意:给出串S1,S2,长度相同,均为小写字母,保证S1<=S2(字典序),现在要求将S1重新排列,得到T,使得S1<T<S2,求这样的T的个数。如果T1=T2,那么认为是一种。
题解:先考虑如何让T<S2,这样求出结果之后,再求一次T<S1,减一下,得到S1<=T<S2,再减1就得到S1<T<S2。
我们可以从第一位向后枚举,在每一位上枚举这一位可以放哪个字母,比如S1是ababa,S2是ububu,那么我们先枚举T第一位放a,那么无论后边怎么放,一定满足T<S2,于是就是算一个有重复元素的全排列,公式是(元素总个数!)/(元素1个数!*元素2个数!*……元素x个数!)。然后这一位可以放的字母范围是‘a’-S2[ i ]-1,枚举结束之后,把这一位放上S2[ i ],然后继续看后边一位,意思是我前缀一段保持和S2相同,让后边的位来分胜负。如果S2[ i ]这种字母用光了,显然我们也就统计完了,因为必须在这一位分出胜负。
于是我们设计了一个n*26*26的算法。然后这算法被卡掉了。。。。。
优化:考虑那个公式(元素总个数!)/(元素1个数!*……元素x个数!)。我们每次往下推进一位,带来的变化是元素总个数-1,某个元素个数-1,于是给这个公式带来的变化就是乘一个数字,除一个数字而已。。。所以可以每次不用重新算这个公式。每次让当前位放上一个字母,算答案的时候,也是只该元素个数-1->乘上一个数字。
优化后:n*26+打表算阶乘和逆元。
代码有点丑,,但还是好理解的,,,因为,,,辣鸡葫芦娃又送了。。。
Code:
#include<bits/stdc++.h>using namespace std;const int maxn = 1e6+100;const int MOD = 1e9+7;int cnt[1000];char s1[maxn],s2[maxn];int n;long long ans =0;long long bas[maxn];long long ni[maxn];inline long long q(long long x,long long y){long long res =1;while (y){if (y&1){res = res*x%MOD;}x = x*x%MOD;y>>=1;}return res;}inline long long calc(int tot){long long res = bas[tot];for (int i='a';i<='z';i++){if (cnt[i])res = res*q(bas[cnt[i]],MOD-2)%MOD;}return res;}int main(){bas[0]=1;ni[0]=1;for (int i=1;i<=1000000;i++){bas[i] = bas[i-1]*i%MOD;ni[i] = q(i,MOD-2);}gets(s1);gets(s2);n =strlen(s1);for (int i=0;i<n;i++){cnt[s1[i]]++;}long long temp =calc(n);for (int i=0;i<n;i++){temp = temp*ni[n-i]%MOD;for (int x='a';x<s2[i];x++){if (cnt[x]){ans+=temp*cnt[x]%MOD;}}ans%=MOD;temp = temp*cnt[s2[i]]%MOD;cnt[s2[i]]--;if (cnt[s2[i]]<0)break;}long long ans1 = ans;ans =0;memcpy(s2,s1,strlen(s1));memset(cnt,0,sizeof cnt);for (int i=0;i<n;i++){cnt[s1[i]]++;}temp =calc(n);for (int i=0;i<n;i++){temp = temp*ni[n-i]%MOD;for (int x='a';x<s2[i];x++){if (cnt[x]){ans+=temp*cnt[x]%MOD;}}ans%=MOD;temp = temp*cnt[s2[i]]%MOD;cnt[s2[i]]--;if (cnt[s2[i]]<0)break;}cout<<(ans1-ans+2*MOD-1)%MOD<<endl;}
阅读全文
0 0
- Codeforces 895D Round#448 2D :组合数学+小学数学优化
- Codeforces Round #448 (Div. 2)D. String Mark(组合数学)
- Codeforces-785D (组合数学)
- Codeforces Round #419 (Div. 2) (Codeforces 815B) D. Karen and Test 组合数学
- Codeforces Round #177 (Div. 2)---D. Polo the Penguin and Houses (组合数学+暴力)
- Codeforces Round #338 (Div. 2)D. Multipliers【费马小定理+组合数学】
- Codeforces Round #369 (Div. 2) D. Directed Roads (dfs+组合数学 图论)
- 组合数学——Codeforces Round #404 (Div. 2) D. Anton and School
- Codeforces Round #258 (Div. 2) D. Count Good Substrings —— 组合数学
- Codeforces 615D Multipliers 【组合数学】
- codeforces 900D(组合数学+剪枝)
- CodeForces 26 D.Tickets(组合数学)
- Educational Codeforces Round 15 D 数学推导
- Codeforces Round #109 (Div. 2) D. Colliders 数学
- Codeforces Round #360 (Div. 2) D. Remainders Game(数学)
- Codeforces Round #364 (Div. 2) D 数学推导
- Codeforces Round #364 (Div. 2) D 数学/公式
- Codeforces 785D 数学
- ntp服务器搭建及客户端配置-使用阿里云
- 使用uncompyle2 反编译pyo
- VUE的学习
- 假如时光倒流,我会这么学习Java
- 解决Android-SDK Manager闪退
- Codeforces 895D Round#448 2D :组合数学+小学数学优化
- 斯里兰卡菩提树下悟道两千年
- Codeforces Round #448 (Div. 2) ABC
- hduoj 2001
- java学习笔记2
- Android选中字体颜色改变
- 做教学直播时,如何做PPT课件直播?
- Android单元测试实践
- 串口