首页 > 代码库 > cf660E Different Subsets For All Tuples

cf660E Different Subsets For All Tuples

For a sequence a of n integers between 1 and m, inclusive, denote f(a) as the number of distinct subsequences of a (including the empty subsequence).

You are given two positive integers n and m. Let S be the set of all sequences of length n consisting of numbers from 1 to m. Compute the sum f(a) over all a in S modulo 109?+?7.

Input

The only line contains two integers n and m (1?≤?n,?m?≤?106) — the number of elements in arrays and the upper bound for elements.

Output

Print the only integer c — the desired sum modulo 109?+?7.

Examples
Input
1 3
Output
6
Input
2 2
Output
14
Input
3 3
Output
174

 

数论题都是一生之敌QAQ

看了一遍官方tutorial没怎么懂,搜题解的时候突然看见Q神orz

 

“E题,强行推公式,枚举长度k,考虑每个长度为k的序列能作为多少个长度为n的序列的子序列,考虑k>=1,记子序列为s[1]s[2]...s[k],位置序列为p[1]p[2]...p[k],为了保证不重不漏,对每个长为n的序列,如果包含s[]作为子序列,找出使得位置序列字典序最小的,这要求p[1]之前不出现s[1],p[1]和p[2]之间不出现s[2],依此类推,枚举最后一个位置q,即q=p[k],那么有C(q-1,k-1)*m^k*(m-1)^(q-k)*m^(n-q),上式对q从k到n,对k从1到n求和,考虑交换求和,先对k从1到q求和,得到m^(n-q+1)*(2m-1)^(q-1),上式对q从1到n求和,这是个等比数列,可以进一步化简,再加上k=0的贡献m^n即可,复杂度O(logn)。”——by Q神

 

空集单独考虑,就最后加上个m^n就行

枚举一个长度len的子序列,假设是x[1]x[2]...x[len],考虑有多少个长度为n的串出现过这个子序列

为了统计不重不漏,只考虑这个子序列第一次出现在这个串中

因为是第一次出现,那么在x[1]之前不能有x[1]同样的,x[1]和x[2]之间不能有x[2]同样的,,,以此类推

所以在x[k]之前其他未定的位置都恰好有(m-1)种取法

x[len]之后就随意了,因为怎么取都不影响x[1]x[2]...x[len]子序列第一个出现,所以都有m种取法

而每个x[i]都有m种取法,

假设最后一个x[len]出现在q位置,前面x[1]~x[len-1]有C(q-1,len-1)种放法

最后答案是C(q-1,len-1)*m^len*(m-1)^(q-len)*m^(n-q)

瞎鸡儿一通化简之后

Σm^(n-len+1)*(2m-1)^(len-1)

 

技术分享
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<queue>
 8 #include<deque>
 9 #include<set>
10 #include<map>
11 #include<ctime>
12 #define LL long long
13 #define inf 0x7ffffff
14 #define pa pair<int,int>
15 #define mkp(a,b) make_pair(a,b)
16 #define pi 3.1415926535897932384626433832795028841971
17 #define mod 1000000007
18 using namespace std;
19 inline LL read()
20 {
21     LL x=0,f=1;char ch=getchar();
22     while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
23     while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
24     return x*f;
25 }
26 LL n,m;
27 inline LL quickpow(LL a,LL b)
28 {
29     LL s=1;
30     while (b)
31     {
32         if (b&1)s=(s*a)%mod;
33         a=(a*a)%mod;
34         b>>=1;
35     }
36     return s;
37 }
38 int main()
39 {
40     n=read();m=read();
41     LL ans=quickpow(m,n);
42     for (int i=1;i<=n;i++)
43     {
44         ans=(ans+quickpow(m,n-i+1)*quickpow(2*m-1,i-1))%mod;
45     }
46     printf("%lld\n",ans);
47 }
cf 660E

 

cf660E Different Subsets For All Tuples