题目描述
众所周知卡农是一种复调音乐的写作技法,小余在听卡农音乐时灵感大发,发明了一种新的音乐谱写规则。他将声音分成 n 个音阶,并将音乐分成若干个片段。音乐的每个片段都是由 1 到 n 个音阶构成的和声,即从 n 个音阶中挑选若干个音阶同时演奏出来。为了强调与卡农的不同,他规定任意两个片段所包含的音阶集合都不同。同时为了保持音乐的规律性,他还规定在一段音乐中每个音阶被奏响的次数为偶数。现在的问题是:小余想知道包含 m 个片段的音乐一共有多少种。两段音乐 a 和 b 同种当且仅当将 a 的片段重新排列后可以得到 b。例如:假设 a
为{{1,2},{2,3}},b 为{{3,2},{2,1}},那么 a 与 b 就是同种音乐。由于种数很多,你只需要
输出答案模 100000007(质数)的结果。
输入输出格式
输入格式:
从文件input.txt中读入数据,输入文件仅一行,具体是用空格隔开的两个正整数n和m,分别表示音阶的数量和音乐中的片段数。20%的数据满足n,m≤5,50%的数据满足n,m≤3000,100%
的数据满足n,m≤1000000。
输出格式:
输出文件 output.txt 仅包含一个非负整数,表示音乐的种数模 100000007 的结果。【输入输出样例】
输入输出样例
输入样例#1:
2 3
输出样例#1:
1
说明
样例解释:音乐为{{1},{2},{1,2}}
首先题目里说是无序的,但是不要管它,我们先把它看成有序的,最后除以一个1种位置,对于每种位置,
]。
)。
d的逆元即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 long long Mod=100000007,s; 7 long long n,m; 8 long long pre[1000001],A[1000001],f[1000001]; 9 long long qpow(long long x,int y) 10 { 11 long long res=1; 12 while (y) 13 { 14 if (y%2==1) 15 { 16 res=(res*x)%Mod; 17 } 18 x=(x*x)%Mod; 19 y/=2; 20 } 21 return res; 22 } 23 int main() 24 {long long i; 25 cin>>n>>m; 26 s=(qpow(2,n)-1+Mod)%Mod; 27 //p=qpow(2,n)%Mod; 28 pre[0]=1; 29 for (i=1;i<=m;i++) 30 { 31 pre[i]=(pre[i-1]*(s-i+1+Mod)%Mod)%Mod; 32 } 33 A[1]=1; 34 for (i=2;i<=m;i++) 35 A[i]=((Mod-Mod/i)*A[Mod%i]+Mod)%Mod; 36 f[1]=0;f[2]=0; 37 for (i=3;i<=m;i++) 38 { 39 f[i]=(pre[i-1]+Mod)%Mod; 40 f[i]=(f[i]-f[i-1]+Mod)%Mod; 41 if (f[i]<0) f[i]+=Mod; 42 f[i]=(f[i]-((f[i-2]*(i-1)%Mod)*((s-i+2+Mod)%Mod))%Mod+Mod)%Mod; 43 if (f[i]<0) f[i]+=Mod; 44 } 45 for (i=1;i<=m;i++) 46 f[m]=(f[m]*A[i])%Mod; 47 cout<<f[m]; 48 }