纪中的联赛模拟
Description
在$wzq$面前摆着一个大箱子,箱子被划分成$n*m$个格子,箱子的侧面是透明的,箱子很高,所以$wzq$只能从侧面观察
现在,箱子中有些格子被不透明的物体塞满了,由于$wzq$只能从侧面看,所以他只知道又哪些行和列又不透明的格子,求有多少种方案满足$wzq$看到的情况,对$ 998244353 $取模
$wzq$对$OI$的造诣太深了,但是他懒得算,所以找到了你这个工具人
对于前$10\%$的数据,保证$1<=n,m<=5$
对于前$30\%$的数据,保证$1<=n,m<=10$
对于前$50\%$的数据,保证$1<=n,m<=500$
对于前$70\%$的数据,保证$1<=n,m<=5000$
对于$100\%$的数据,保证$1<=n,m<=10^6$
[只有图片题面x]
sol:
因为一些原因早上少了快一个半小时的比赛时间……然后又打了半小时东方CB233
结果到结束就只切了这个垃圾签到题==[我太菜了]
考虑转化一下模型
题目就是给定$n‘$[$B$的个数]个不为空的二进制数,问又多少种方案能使得或和的答案是一个给定的二进制数$ M $
这东西的模型上次在CF见过来着==[然后加强了一堆限制 变成了一个数据结构题]
因为是二进制,显然的拆位考虑
对于不考虑不为空限制的情况下 答案显然为$(2^{n}-1)^{m}$[每一位二进制数都是随机填 但是不全为空]
考虑加入限制,也是一个显然的容斥,行的限制可以化简为原问题的一个子问题 答案就是$\sum (-1)^iC_{n‘}^{i}*(2^{n-i}-1)^m$
然后就做完了== 不愧是简单签到题.jpg[写完就继续去颓东方CB了233]
总效率 $O(n log n)$
Code
#include <bits/stdc++.h> using namespace std; const long long fish=998244353; int N,M;long long fac[1000005],inv[1000005]; long long Pow(int x,int y){ long long ans=1; for (;y;y>>=1,x=1ll*x*1ll*x%fish) if (y&1) ans=1ll*ans*1ll*x%fish; return ans; } void Pre(){ fac[0]=1; for (int i=1;i<=1000000;i++) fac[i]=1ll*fac[i-1]*1ll*i%fish; inv[1000000]=Pow(fac[1000000],fish-2); for (int i=999999;i>=0;i--){ inv[i]=1ll*inv[i+1]*1ll*(i+1)%fish; } } int C(int n,int r){ return 1ll*fac[n]*1ll*inv[r]%fish*inv[n-r]%fish; } int main(){ scanf("%d%d",&N,&M); Pre(); int cnt1=0,cnt=0,cnt2=0; for (int i=1;i<=N;i++){ char c; cin>>c; if (c==‘B‘) cnt2++; } for (int i=1;i<=M;i++){ char c; cin>>c; if (c==‘B‘) cnt1++; } long long ans=Pow(Pow(2,cnt2)-1,cnt1); long long xs=-1; for (int i=1;i<=cnt2;i++){ ans=(ans+1ll*xs*1ll*C(cnt2,i)%fish*1ll*Pow(Pow(2,cnt2-i)-1,cnt1)%fish)%fish; if (ans<0) ans=(ans+fish)%fish; xs=-xs; } cout<<ans; return 0; }
原文地址:https://www.cnblogs.com/si--nian/p/11747682.html