NOI模拟 开关
1.NOIP模拟 排序2.NFLS 231031 比赛总结3.JOI2013Final/LOJ2763 现代豪宅4.省选模拟 序列5.省选模拟 过路费6.NOI模拟 序列7.NOI模拟 大战波特8.NOI模拟 Mizuki 与进化9.NOI模拟 刀客球10.NOI模拟 真夏は誰のモノ11.NOI模拟 树数术12.NOI模拟 序列13.NOI模拟 GCD
14.NOI模拟 开关
15.NOI模拟 排序幻觉16.NOI模拟 UTF-817.NOI模拟 捉迷藏18.退背包简介/NOI模拟 卖画19.CSP模拟 取模20.CSP模拟 矩阵操作21.AGC007F Shik and Copying String22.洛谷P10336 [UESTCPC 2024] 2-聚类算法23.NFLS 241014 比赛总结24.QOJ5173 染色25.洛谷P11183 [ROIR 2018 Day2] 大数据处理涉及知识点:DP,组合数学
题意
盏灯,可以做 次操作,每次操作表示为一个长度为 的 串 , 为 表示该对灯 的开关状态反转,一种关灯方法即为 个两两不同的 串组成的无序集合。现在 盏灯中前 盏是亮的,其他是灭的,请问有多少种关灯方法能恰好 次操作关掉所有灯,答案模 。
思路
学到一个非常好用的计数技巧:我们发现要计数的是集合这个要求很烦,但我们可以先求出有序情况下的答案,然后再除以阶乘,类比 要比 多除以一个 。对应到这道题,我们先求出有多少种不同的操作序列能关掉所有的灯,然后除以 得到答案(有序序列 无序集合)。
还可以发现一件事,因为最开始前 盏灯亮着而最后要全熄灭,因此所有操作的 串按位异或之后一定为前 位为 ,其他为 的串。说明假设已经确定了前 个操作,第 次操作也就确定了,由此为转移进行 DP:
记 为 时的答案,
为前 个两两不同的操作有多少种组合,但我们第 次操作的 串有可能会和之前 个操作重复,因此要减去重复的部分。前 个串中有 个和第 个重复,由于两两不同,那么剩下 个串是不和第 个重复的,对于每种不重复的 个串的组合(共 种),重复的那个串只有可能是剩下的 种,并且这个串的位置有可能是前 个中的任意一个地方,因此需要重复的部分总共有 种。
代码
代码中预处理了 和 ,同时将 化为了
#include<bits/stdc++.h>
using namespace std;
#ifdef ONLINE_JUDGE
#define getchar __getchar
inline char __getchar(){
static char ch[1<<20],*l,*r;
return (l==r&&(r=(l=ch)+fread(ch,1,1<<20,stdin),l==r))?EOF:*l++;
}
#endif
template<class T>inline void rd(T &x){
T res=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while('0'<=ch && ch<='9'){res=res*10+ch-'0';ch=getchar();}
x=res*f;
}
template<class T>inline void wt(T x,char endch='\0'){
static char wtbuff[20];
static int wtptr;
if(x==0){
putchar('0');
}
else{
if(x<0){x=-x;putchar('-');}
wtptr=0;
while(x){wtbuff[wtptr++]=x%10+'0';x/=10;}
while(wtptr--) putchar(wtbuff[wtptr]);
}
if(endch!='\0') putchar(endch);
}
typedef long long LL;
const LL P=19260817,MAXN=1005;
LL n,m,v,fact[MAXN],c[MAXN],n2n,f[MAXN];
inline LL qpow(LL x,LL a){
LL res=1;
x%=P;
while(a){
if(a&1) res=res*x%P;
x=x*x%P;
a>>=1;
}
return res;
}
inline void solve(){
rd(n);rd(m);rd(v);
n2n=qpow(2,n);
c[0]=1;
for(LL i=1;i<m;i++){
c[i]=c[i-1]*((n2n-i+1+P)%P)%P*qpow(i,P-2)%P;
}
f[0]=(v==0);
f[1]=1;
for(int i=2;i<=m;i++){
f[i]=(fact[i-1]*c[i-1]%P - (i-1)*( (n2n-i+2+P)%P )%P*f[i-2]%P +P)%P;
}
wt(f[m]*qpow(fact[m],P-2)%P,'\n');
}
int main(){
fact[0]=1;
fact[1]=1;
for(LL i=2;i<MAXN;i++){
fact[i]=fact[i-1]*i%P;
}
int t;
rd(t);
while(t--) solve();
return 0;
}
本文作者:MessageBoxA
本文链接:https://www.cnblogs.com/SkyNet-PKN/p/18215666
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步