洛谷 P3214 [HNOI2011]卡农
2017-04-21 09:08
190 查看
题目描述
众所周知卡农是一种复调音乐的写作技法,小余在听卡农音乐时灵感大发,发明了一种新的音乐谱写规则。他将声音分成 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}}
【分析】
为大家分享一个被1000000007与1e9+7的不同卡炸的人…
从此得到经验教训:mod不能写成1e9+7…(尼玛鬼才能检查出来啊喂)
题有点麻烦…但是不算难想(虽然最后还是看了题解)
我们先把它变成有序的,最后除一个m!
对于有序的方案数我们考虑补集转换。
首先所有的子集个数应该是2^n-1;
我们定义f[i]为使用i个盘子的方案数。
因为要保证总数是偶数。也就是说如果你确定了i-1个盘子第i个盘子也就确定了
所以总数应该是A(2^n-1,i-1);
这样肯定多算了。具体来说有两部分。
1.如果前i-1个已经合法,那么第i个就是空集。这样肯定不合法。所以要减去f[i-1]
2.如果根据前i-1个确定出来的第i个集合和前面的某一个重复,这样肯定是不合法的。
对于第2种情况。
因为考虑顺序,所以那个和第i个重复的集合有i-1种位置.
对于每种位置。当前已经满足偶数了,去掉两个集合之后还是偶数。
所以剩下其他集合的方案数为f[i-2]。
然后我们需要算出有多少种可能重复的方案
因为我们已经确定了(i-2)个位置,所以方案数为(2^n-1-(i-2));
最后再乘上一个m!关于P的逆元即可。
以上转自 sunshinezff
本来已经考虑到第二种情况了…结果果断觉得这压根没法求…于是看了眼题解发现确实是这样的…OrzOrzOrz 所以说做一道题不能轻易放弃…
【代码】
众所周知卡农是一种复调音乐的写作技法,小余在听卡农音乐时灵感大发,发明了一种新的音乐谱写规则。他将声音分成 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}}
【分析】
为大家分享一个被1000000007与1e9+7的不同卡炸的人…
从此得到经验教训:mod不能写成1e9+7…(尼玛鬼才能检查出来啊喂)
题有点麻烦…但是不算难想(虽然最后还是看了题解)
我们先把它变成有序的,最后除一个m!
对于有序的方案数我们考虑补集转换。
首先所有的子集个数应该是2^n-1;
我们定义f[i]为使用i个盘子的方案数。
因为要保证总数是偶数。也就是说如果你确定了i-1个盘子第i个盘子也就确定了
所以总数应该是A(2^n-1,i-1);
这样肯定多算了。具体来说有两部分。
1.如果前i-1个已经合法,那么第i个就是空集。这样肯定不合法。所以要减去f[i-1]
2.如果根据前i-1个确定出来的第i个集合和前面的某一个重复,这样肯定是不合法的。
对于第2种情况。
因为考虑顺序,所以那个和第i个重复的集合有i-1种位置.
对于每种位置。当前已经满足偶数了,去掉两个集合之后还是偶数。
所以剩下其他集合的方案数为f[i-2]。
然后我们需要算出有多少种可能重复的方案
因为我们已经确定了(i-2)个位置,所以方案数为(2^n-1-(i-2));
最后再乘上一个m!关于P的逆元即可。
以上转自 sunshinezff
本来已经考虑到第二种情况了…结果果断觉得这压根没法求…于是看了眼题解发现确实是这样的…OrzOrzOrz 所以说做一道题不能轻易放弃…
【代码】
//[HNOI 2011] 卡农 #include<iostream> #include<cstring> #include<cstdio> #define ll long long #define M(a) memset(a,0,sizeof a) #define fo(i,j,k) for(i=j;i<=k;i++) using namespace std; const ll mod=100000007; ll n,m,ans=1; ll fac[1000005],res[1000005]; inline ll ksm(ll x,ll k) { if(k==1) return x; ll tmp=ksm(x,k>>1); if(k&1) return (tmp*tmp%mod)*x%mod; return tmp*tmp%mod; } int main() { int i,j; scanf("%lld%lld",&n,&m); ll czy=ksm(2,n); czy=(czy+mod)%mod; fo(i,1,m-1) { ans=( ans*(czy-i) )%mod; res[i+1]=((ans-res[i])%mod+mod)%mod; res[i+1]=(res[i+1]-(res[i-1]*(czy-i)%mod)*i%mod+mod)%mod; res[i+1]=(res[i+1]%mod+mod)%mod; res[1]=res[2]=0; } fac[0]=1;fo(i,1,m) fac[i]=fac[i-1]*i%mod; ans=(res[m]*ksm(fac[m],mod-2))%mod; printf("%lld\n",(ans+mod)%mod); return 0; }
相关文章推荐
- [BZOJ2339][HNOI2011]卡农(DP+组合数学)
- 洛谷P3216 [HNOI2011]数学作业
- 排列 [HNOI2011]卡农
- bzoj2339: [HNOI2011]卡农
- 2339: [HNOI2011]卡农
- [HNOI2011]卡农
- BZOJ.2339.[HNOI2011]卡农(思路 DP 组合 容斥)
- 【BZOJ2339】【HNOI2011】卡农
- bzoj 2339: [HNOI2011]卡农 组合数学+递推
- Bzoj2339--Hnoi2011卡农
- bzoj 2339: [HNOI2011]卡农
- 【BZOJ2339】[HNOI2011]卡农 组合数+容斥
- BZOJ 2339 【HNOI2011】 卡农
- [BZOJ 2339][HNOI 2011]卡农(组合数学)
- 洛谷 P3211 [HNOI2011]XOR和路径(推dp+高斯消元)
- [HNOI 2011]卡农
- bzoj2339 [HNOI2011]卡农
- BZOJ 2339: [HNOI2011]卡农
- BZOJ 2339 HNOI2011 卡农 组合数学
- [HNOI2011]卡农