看了官方题解+q神的讲解才懂。。。
智商问题。。
讲道理。。数学真的比脱单难啊。。。
题目链接:
http://codeforces.com/problemset/problem/660/E
题意:
给定数字范围,问由这些数字组成的长度为n的串的子序列有多少种?
分析:
方法一:
枚举长度k,计算以其为子序列的原串种数。
最后枚举
这样对于每个
令
后一项求和利用二项式定理进行化简,最终得到
代码:
#include <iostream>
using namespace std;
const int mod = 1e9 + 7;
int quick_pow(int a, int b)
{
int ans = 1;
for(;b;b >>= 1, a = a * 1ll * a % mod){
if(b & 1) ans = ans * 1ll * a % mod;
}
return ans;
}
int main()
{
int n, m;cin>>n>>m;
int ans = quick_pow(m, n);
for(int s = 1; s <= n; s ++)
ans = (ans + quick_pow(m, n - s+ 1) * 1ll * quick_pow( 2 * m - 1, s - 1)) % mod;
cout<<ans<<endl;
return 0;
}
然后可以发现这个就是个等比数列。
最后不要忘记加上空串的
#include <iostream>
using namespace std;
const int mod = 1e9 + 7;
int quick_pow(int a, int b)
{
int ans = 1;
for(;b;b >>= 1, a = a * 1ll * a % mod){
if(b & 1) ans = ans * 1ll * a % mod;
}
return ans;
}
int main()
{
int n, m;cin>>n>>m;
int ans ;
if(m == 1) ans = n + 1;
else
ans = (quick_pow(m, n) + m * 1ll * (quick_pow(2 * m - 1, n) - quick_pow(m, n)) % mod * quick_pow(m - 1, mod - 2) % mod) % mod;
cout<<ans<<endl;
return 0;
}
方法二:
还有一种卿学姐的dp方法。。