【JZOJ 4812】【NOIP2016提高组 五校联考2】string
2016-10-06 22:00
561 查看
Description
给出一个长度为n, 由小写英文字母组成的字符串S, 求在所有由小写英文字母组成且长度为n 且恰好有k 位与S 不同的字符串中,给定字符串T 按照字典序排在第几位。由于答案可能很大,模10^9 + 7 输出。
对于100% 的数据,k<=n<=10^5
Analysis
其实扫一遍就好了。一开始好傻没想到正解比赛过了1.5h才恍然大悟。
其实就是算有多少个串比该串小,那么类似于数位DP的思路,就会发现没了限制之后方案数可以O(1)算。主要看代码吧。
Code
#include<cstdio> #include<algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) using namespace std; typedef long long ll; const int N=100010,mo=1e9+7; char a ,b ; ll n,k,fac ; ll qmi(ll x,ll n) { ll t=1; for(;n;n>>=1) { if(n&1) t=t*x%mo; x=x*x%mo; } return t; } ll ny(ll x) { return qmi(x,mo-2); } ll calc(ll n,ll k) { if(n<k) return 0; return qmi(25,k)*fac %mo*ny(fac[k]*fac[n-k]%mo)%mo; } int main() { freopen("string.in","r",stdin); freopen("string.out","w",stdout); scanf("%lld %lld",&n,&k); fac[0]=1; fo(i,1,n) fac[i]=fac[i-1]*i%mo; scanf("%s\n%s",a+1,b+1); ll ans=0; fo(i,1,n) { if(a[i]<b[i]) { ans=(ans+(b[i]-'a'-1)*calc(n-i,k-1)%mo+calc(n-i,k))%mo; k--; } else { ans=(ans+(b[i]-'a')*calc(n-i,k-1)%mo)%mo; if(a[i]>b[i]) k--; } if(!k) break; } printf("%lld",ans+1); return 0; }
相关文章推荐
- JZOJ 4812 【NOIP2016提高A组五校联考2】string
- 【JZOJ4812】【NOIP2016提高A组五校联考2】string
- [jzoj 4812]【NOIP2016提高A组五校联考2】string
- JZOJ 4813 【NOIP2016提高A组五校联考2】running
- JZOJ 4817. 【NOIP2016提高A组五校联考4】square
- 【jzoj 4814】【NOIP2016提高A组五校联考2】tree
- JZOJ 4815 【NOIP2016提高A组五校联考4】ksum
- JZOJ 4814 【NOIP2016提高A组五校联考2】tree
- 【JZOJ 4814】【NOIP2016提高组 五校联考2】tree
- 【JZOJ 4810】【NOIP2016提高组 五校联考1】道路规划
- 【NOIP2016提高A组五校联考2】string
- JZOJ 4817 【NOIP2016提高A组五校联考4】square
- 【JZOJ4815】【NOIP2016提高A组五校联考4】ksum
- JZOJ 4806 【NOIP2016提高A组五校联考3】打工
- {题解}[jzoj4817]【NOIP2016提高A组五校联考4】square
- 【JZOJ4816】【NOIP2016提高A组五校联考4】label
- JZOJ 4814. 【NOIP2016提高A组五校联考2】tree
- 【NOIP2016提高A组五校联考2】string
- 【JZOJ 4811】【NOIP2016提高组 五校联考1】排队
- 【JZOJ 4813】【NOIP2016提高组 五校联考2】running