题目大意:
给定一个包含数字,空格和拉丁字母的字符串。现在可以在单词之间,字符串开头和末尾处添加字符,可以将
A,B,C,E,H,K,M,O,P,T,X,a,c,e,o,p,x,y
替换成相应的俄文字母,问长度在
[q,c]
内的替换后的字符串有多少种,满足初始字符串长度在
[q,c]
内。
分析:
对于某一个长度
L
,我们设原长为
F
单词数为
S
,可替换的字母总数为
T
,那么方案数就是
2T(L−F+1S)
,不知道为啥的还是去补补基本的组合数学吧。。。
记得还要用
unsigned long long
。
AC code:
#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define clr(a, b) memset(a, b, sizeof a)
#define rep(i, a, b) for(int i = (a); i <= (b); ++i)
#define per(i, a, b) for(int i = (a); i >= (b); --i)
typedef unsigned long long ULL;
typedef long long LL;
typedef double DB;
typedef long double LD;
using namespace std;
void open_init()
{
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
ios::sync_with_stdio(0);
}
void close_file()
{
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
}
const string rus = "ABCEHKMOPTXaceopxy";
int q, c, sum, l;
vector<string> s;
ULL base, ans;
ULL C(int n, int m)
{
ULL ret = 1;
rep(i, 0, m-1)
ret = ret*(n-i)/(i+1);
return ret;
}
int main()
{
open_init();
string tmp;
cin >> q >> c;
while(cin >> tmp)
{
s.pb(tmp);
l += tmp.size();
rep(i, 0, tmp.size()-1)
rep(j, 0, rus.size()-1)
if(tmp[i] == rus[j])
{
sum++;
break;
}
}
base = 1LL<<sum;
int n = s.size();
rep(i, q, c)
{
int now = i-l+1;
if(now < n) continue;
ans += C(now, n);
}
ans *= base;ans--;
cout << ans << endl;
close_file();
return 0;
}