[HNOI2011] 卡农 题解
题目传送门
提交记录😭😭😭#
[HNOI2011] 卡农
题目描述#
众所周知卡农是一种复调音乐的写作技法,小余在听卡农音乐时灵感大发,发明了一种新的音乐谱写规则。
他将声音分成
为了强调与卡农的不同,他规定任意两个片段所包含的音阶集合都不同。同时为了保持音乐的规律性,他还规定在一段音乐中每个音阶被奏响的次数为偶数。
现在的问题是:小余想知道包含
两段音乐
答案对
输入格式#
仅一行两个正整数
输出格式#
输出一行一个整数表示答案。
样例 #1#
样例输入 #1#
2 3
样例输出 #1#
1
提示#
【数据范围】
对于
对于
对于
【样例解释】
音乐为
呃呃#
打了半天一直RE20分 发布帖子求助后得到思路www🥵🥵🥵
思路、#
一个集合的非空集合共有
简化题意就是
(1)所有选出的
(2)所有选出的
(3)所有选出的
先考虑没有三个限制条件的情况#
在
然后需要减去不符合三个条件的情况:
使用二进制思想考虑#
如果每个元素出现的次数都是偶数,那么它们的异或一定是0
例:
先考虑第三个条件#
(3).1到
考虑第
我们发现,如果前
因为对于任意一个元素
如果前
所以 加上限制 后,方案数为 #
🥰
再考虑第一个条件#
对于
则最后一个集合为了满足条件
对于
或者前
🥰
考虑第二个限制条件#
我们需要减去第
如果我们把相同的两个子集都删去,那么剩下的
所以重复的方案数为:
考虑最后一个问题#
有些 方案 被重复计算了怎么办?
最难思考的地方呜呜呜#
我们随便找一个集合
对于这个问题,我们只需考虑一个合法的
即
总结#
考虑化简 #
其他题都是预处理出阶乘和阶乘的逆元再用函数输出
for(register int i=1;i<=1e6+5;i++){
x[i]=x[i-1]*i%mod;
y[i]=y[i-1]*(qpow(i,mod-2))%mod;
// z[i]=qpow(i,mod-2)%mod;
}
inline int C(int n,int m){
if(n<m) return 0;
return ((x[n]%mod*y[n-m]%mod)%mod*y[m]%mod)%mod;
}
但是我们可以发现 组合数不能这么算的。你代码中的
递推
递推完了!
然后注意一下除法需要用费马小定理处理逆元,因为
int c=((((op-1)*niyuan(2)))%mod*((op)%mod))%mod;
最后附上AC代码#
#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace Testify{
inline int read(){
int f(1),x(0);
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);
return f*x;
}
inline void Write(int x){
if(x>9) Write(x/10);
putchar(x%10+'0');
}
inline void write(int x){
if(x<0) putchar('-'),x=-x;
Write(x);
putchar('\n');
}
}
using namespace Testify;
const int mod=1e8+7;
const int N=1e6+114514;
int n,m,dp[N],x[N],y[N];
inline int qpow(int a,int b){
int res=1;
while(b){
if(b&1) res=res*a%mod;
b>>=1;
a=a*a%mod;
}
return res;
}
inline int C(int n,int m){
if(n<m) return 0;
return ((x[n]%mod*y[n-m]%mod)%mod*y[m]%mod)%mod;
}
inline int niyuan(int n){
return qpow(n,mod-2)%mod;
}
signed main(void){
n=read(),m=read();
x[0]=y[0]=1;
int op=qpow(2,n)-1;
op=((op%mod)+mod)%mod;
// cerr<<"op: "<<op<<endl;
if(op<m){
write(0);
return 0;
}
// for(register int i=1;i<=op+1;i++){
// x[i]=x[i-1]*i%mod;
// y[i]=y[i-1]*(qpow(i,mod-2))%mod;
// }
// int aa=x[op];
// int c=(x[op]%mod*y[2]%mod*y[op-2]%mod)%mod;
// int c=op*(op+mod-1)%mod+qpow(2,mod-2)%mod;
int c=((((op-1)*niyuan(2)))%mod*((op)%mod))%mod;
// cerr<<"C: ";
// clog<<C(op,2)<<endl;
dp[1]=0,dp[2]=0;
for(register int i=3;i<=m;i++){
dp[i]=((c-dp[i-1]-(dp[i-2]*(op-(i-2))))%mod+mod)%mod*niyuan(i)%mod;
// c=(c%mod*y[i]%mod*y[op-i]%mod)%mod;
// c=c*(op-i+1+(int)mod)%mod*qpow(i,mod-2)%mod;
// c=(c*(op-(i-1))*((qpow(i-1,mod-2)%mod)))%mod;
c=((c*(((op-(i-1)))%mod+mod)%mod)%mod*niyuan(i))%mod;
// c=c*(op-(i-1))
}
write(dp[m]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现