题目描述

Description

Input

Output

Sample Input

3 2 3

3 6 5

1 2

1 3

Sample Output

15

Data Constraint

题解

迫真CSP模拟

简单容斥(×)

容斥套dp套容斥套dp(√)


先把lim按从小到大排序,同时把边的编号也改过来

考虑没有边时怎么做

枚举一个数位i,假设在i之前的n个数都等于lim,并且要保证i以前的异或和等于C的对应位置

如果i这一位上有一些数没有等于lim,那么先把一个没有等于lim的数x提出来,然后再填其他的数

其他的数在不超过限制(或在第i位已经小于lim)的情况下随便填,x必然有唯一一种填法使得答案为C

所以可以直接算,把小于lim的乘上2^i,等于lim的乘上后面的那一段

最后除以2^i后加进去

要考虑全部等于lim的情况和C=0时空集的答案为1

这一部分是O(2^n*n*64)的


接着考虑有边的情况

对于一条边,将其容斥成 无限制-相等,最后变成至少为0-至少为1+至少为2...的形式

简单证明(二项式反演的套路):

对于有m(m>=0)条边相等时,一种方案被算的次数

\(ans=\sum_{i=0}^{m}{(-1)^i(_i^m)}\)

\(=\sum_{i=0}^{m}{(-1)^i(_i^m)*1^{m-i}}\)

\(=\sum_{i=0}^{m}{(-1)^i(_i^m)*1^{m-i}}\)

\(=(-1+1)^m\)

\(=[m=0]\)

显然只有m=0时的方案才会被算到


容斥完之后,可以发现变成了若干连通块,每个连通块内的值都相等

考虑计算每个连通块的容斥系数之和

由于要保证连通,所以可以用 所有方案-不连通 来算

对于m条边的所有方案容斥系数之和:

\(=\sum_{i=0}^{m}{(-1)^i(^m_i)}\)

然后就和上面一样了

(但是实际上这个式子和上面的含义是不同的,上面的可能有>m条边)

所以所有方案就是[边数=0],不连通的可以先枚举最小的点所在块,然后乘以剩下的随便选的方案

要预处理每个点集中随便选的方案,时间为O(2^n*n^2)

(但是只要有一条边就可以退了,所以跑不满)

处理容斥的时间复杂度为O(3^n)


处理完容斥系数和答案后,考虑把它们合起来,每次加上当前剩余未加的最小点所在块(不会算重)

对于一种情况,假设已经知道了容斥系数和每个块的大小和块中最小的lim

那么对于大小为偶数的块,显然异或后影响为0,所以方案乘上(最小的lim+1)

对于大小为奇数的块,异或后会剩下一个0~lim

全部n个数做完之后可能会剩下若干个数,此时就相当于没有限制的情况了

设一个三进制状态,表示每个数没选/选了且是剩下的/选的但不是剩下的(0/1/2)

递归转移,每次存 当前的三进制状态、有那些位是最小的、有哪些位还没选(后面两个是二进制)

这样避免了直接枚举后拆状态的O(n)

转移就在没选的位上找子集,如果选满了就乘上剩下的贡献后加到答案里

仍要预处理出每个二进制子集的大小和对应的三进制(如果子集大小为奇数则最小的为1其余为2,否则全为2)

预处理的时间为O(2^n*n)

最终dp的时间:由于每次选的是最小点,设当前的最小点为i

那么时间为\(\sum_{i=1}^{n}{2^{i-1}*3^{n-i}}\)

因为前i-1位只能是1或2,后n-i位只能是0或2,所以枚举前面的就是\(2^{i-1}\),枚举i+1~n相当于一个(n-i)大小的子集转移问题

求和一下大约等于O(3^n)

然而直接写会挂,因为直接枚举的时间是O(4^n)

其实只要dp不为0时再转移就可以做到O(3^n)了

code

  1. #include <algorithm>
  2. #include <iostream>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <cstdio>
  6. #define fo(a,b,c) for (a=b; a<=c; a++)
  7. #define fd(a,b,c) for (a=b; a>=c; a--)
  8. #define add(a,b) a=((a)+(b))%998244353
  9. #define low(x) (x&-(x))
  10. #define mod 998244353
  11. #define Mod 998244351
  12. using namespace std;
  13. struct type{
  14. long long s;
  15. int id;
  16. } b[16];
  17. bool c[60];
  18. long long p[60];
  19. long long P[60];
  20. long long P2[60];
  21. int p3[15];
  22. int a[301][2];
  23. int ls[16];
  24. int tot[32768];
  25. int h[32768];
  26. long long H[32768];
  27. long long f[32768];
  28. long long G[32768];
  29. long long g[32768];
  30. long long dp[14348907];
  31. long long lim[16];
  32. bool d[16][60];
  33. long long D[16][60];
  34. int num[16];
  35. int L,n,m,i,j,k,l,len,Tot;
  36. long long C,ans;
  37. bool cmp(type a,type b)
  38. {
  39. return a.s<b.s;
  40. }
  41. void New(int x,int y)
  42. {
  43. ++len;
  44. a[len][0]=y;
  45. a[len][1]=ls[x];
  46. ls[x]=len;
  47. }
  48. long long qpower(long long a,int b)
  49. {
  50. long long ans=1;
  51. while (b)
  52. {
  53. if (b&1)
  54. ans=ans*a%mod;
  55. a=a*a%mod;
  56. b>>=1;
  57. }
  58. return ans;
  59. }
  60. void work1()
  61. {
  62. long long g[2][2];
  63. long long G[2][2];
  64. long long S;
  65. int i,j,k,l,s,I;
  66. bool bz;
  67. memset(g,0,sizeof(g));
  68. memset(G,0,sizeof(G));
  69. f[0]=C==0;
  70. fo(s,1,L)
  71. {
  72. fd(i,59,0)
  73. {
  74. g[0][0]=1;g[0][1]=0;
  75. g[1][0]=0;g[1][1]=0;
  76. fo(j,1,n)
  77. if (p[j-1]&s)
  78. {
  79. fo(k,0,1)
  80. {
  81. fo(l,0,1)
  82. {
  83. fo(I,0,d[j][i])
  84. {
  85. if (I<d[j][i])
  86. add(G[1][l^I],g[k][l]*P[i]);
  87. else
  88. {
  89. if (i)
  90. add(G[k][l^I],g[k][l]*D[j][i-1]);
  91. else
  92. add(G[k][l^I],g[k][l]);
  93. }
  94. }
  95. }
  96. }
  97. fo(k,0,1)
  98. {
  99. fo(l,0,1)
  100. g[k][l]=G[k][l],G[k][l]=0;
  101. }
  102. }
  103. add(f[s],g[1][c[i]]*P2[i]);
  104. bz=0;
  105. fo(j,1,n)
  106. if (p[j-1]&s)
  107. bz^=d[j][i];
  108. if (bz!=c[i])
  109. break;
  110. }
  111. S=0;
  112. fo(i,1,n)
  113. if (s&p[i-1])
  114. S^=lim[i];
  115. f[s]+=S==C;
  116. }
  117. }
  118. void work1_5()
  119. {
  120. int i,j,k,s;
  121. fo(s,1,L)
  122. {
  123. l=low(s);
  124. k=0;
  125. fo(i,1,n)
  126. if (s&p[i-1])
  127. {
  128. for (j=ls[i]; j; j=a[j][1])
  129. if (i<a[j][0] && s&p[a[j][0]-1])
  130. {
  131. ++k;
  132. break;
  133. }
  134. }
  135. G[s]=(k==0);
  136. }
  137. }
  138. void work2()
  139. {
  140. int s,s1;
  141. fo(s,1,L)
  142. {
  143. l=low(s);
  144. g[s]=G[s];
  145. for (s1=(s-1)&s; s1; s1=(s1-1)&s)
  146. if (s1&l)
  147. add(g[s],-g[s1]*G[s^s1]);
  148. }
  149. }
  150. void work2_5()
  151. {
  152. int i,s,bz;
  153. fo(s,1,L)
  154. {
  155. bz=-1;
  156. fo(i,0,n-1)
  157. if (s&p[i])
  158. {
  159. ++tot[s];
  160. if (bz==-1)
  161. h[s]+=p3[i],bz=i;
  162. else
  163. h[s]+=p3[i]*2;
  164. }
  165. if (!(tot[s]&1))
  166. {
  167. h[s]+=p3[bz];
  168. H[s]=(lim[bz+1]+1)%mod;
  169. }
  170. }
  171. }
  172. void work3(int t,int s1,int s2,int s3) //s2:1 s3:0
  173. {
  174. int l,S,s;
  175. if (t>n)
  176. {
  177. if (dp[s1])
  178. {
  179. if (s3)
  180. {
  181. l=low(s3);
  182. S=s3^l;
  183. for (register int s4=S; s4; s4=(s4-1)&S,++Tot)
  184. {
  185. s=s4^l;
  186. if (tot[s]&1)
  187. add(dp[s1+h[s]],dp[s1]*g[s]);
  188. else
  189. add(dp[s1+h[s]],dp[s1]*g[s]%mod*H[s]);
  190. }
  191. if (tot[l]&1)
  192. add(dp[s1+h[l]],dp[s1]*g[l]);
  193. else
  194. add(dp[s1+h[l]],dp[s1]*g[l]%mod*H[l]);
  195. }
  196. else
  197. add(ans,dp[s1]*f[s2]);
  198. }
  199. return;
  200. }
  201. work3(t+1,s1,s2,s3+p[t-1]); //0
  202. work3(t+1,s1+p3[t-1],s2+p[t-1],s3);//1
  203. work3(t+1,s1+2*p3[t-1],s2,s3); //2
  204. }
  205. int main()
  206. {
  207. freopen("draw.in","r",stdin);
  208. freopen("draw.out","w",stdout);
  209. p[0]=P[0]=P2[i]=1;p3[0]=1;
  210. fo(i,1,59)
  211. {
  212. p[i]=p[i-1]*2;
  213. if (i<=14)
  214. p3[i]=p3[i-1]*3;
  215. P[i]=p[i]%mod;
  216. P2[i]=qpower(P[i],Mod);
  217. }
  218. scanf("%d%d%lld",&n,&m,&C);L=p[n]-1;
  219. fo(i,1,n)
  220. scanf("%lld",&lim[i]),b[i]={lim[i],i};
  221. fo(i,0,59)
  222. c[i]=(C&p[i])>0;
  223. sort(b+1,b+n+1,cmp);
  224. fo(i,1,n)
  225. {
  226. num[b[i].id]=i;
  227. lim[i]=b[i].s;
  228. }
  229. fo(i,1,n)
  230. {
  231. fo(j,0,59)
  232. {
  233. d[i][j]=(lim[i]&p[j])>0;
  234. if (j)
  235. D[i][j]=D[i][j-1];
  236. else
  237. D[i][j]=1;
  238. add(D[i][j],d[i][j]*p[j]);
  239. }
  240. }
  241. fo(i,1,m)
  242. {
  243. scanf("%d%d",&j,&k);
  244. j=num[j],k=num[k];
  245. New(j,k);
  246. New(k,j);
  247. }
  248. work1();
  249. work1_5();
  250. work2();
  251. work2_5();
  252. dp[0]=1;
  253. work3(1,0,0,0);
  254. printf("%lld\n",(ans+mod)%mod);
  255. fclose(stdin);
  256. fclose(stdout);
  257. return 0;
  258. }

6423. 【NOIP2019模拟11.11】画的更多相关文章

  1. 6424. 【NOIP2019模拟2019.11.13】我的订书机之恋

    题目描述 Description Input Output Sample Input 见下载 Sample Output 见下载 Data Constraint 题解 lj题卡线段树 求出每个右端点往 ...

  2. 【NOIP2019模拟2019.11.13】旅行 && GDKOI2018 还念(二分答案+dij)

    Description: 题解: 显然满足二分性. 并且每一条边要不选l要不选r. 二分的那条链肯定要选l. 考虑有两个人在走最短路,一个人一开始必须走二分的那条链,要求第一个人走的比第二个人快. 安 ...

  3. NOIp 11.11/12

    最后一场比较正式的NOIp模拟赛,写一发小总结.题目没什么好说的,大部分很简单,先贴一下代码. 1111 T1 //string //by Cydiater //2016.11.11 #include ...

  4. 11.11光棍节工作心得——github/MVP

    11.11光棍节工作心得 1.根据scrum meeting thirdday中前辈的指导进行学习 我在博客中贴了链接,竟然TrackBack引来了原博主,

  5. 下面程序的输出结果是____ A:11,10 B:11,11 C:10,10 D:10,11 int x=10; int y=x++; printf("%d,%d",(x++,y),y++);

    下面程序的输出结果是____ A:11,10 B:11,11 C:10,10 D:10,11 int x=10; int y=x++; printf("%d,%d",(x++,y) ...

  6. Hadoop格式化 From hu-hadoop1/192.168.11.11 to hu-hadoop2:8485 failed on connection exception: java.net.

    192.168.11.12:8485: Call From hu-hadoop1/192.168.11.11 to hu-hadoop2:8485 failed on connection excep ...

  7. 〖Linux〗iptables端口转发(11.11.136.80:5552 <==> 10.10.136.1:8055/11.11.136.1:8055)

    环境: pc1: 10.10.72.1 (network: 10.10.72.0/22) pc2: 地址1: 10.10.136.1 (nework: 10.10.136.0/22) 地址2: 11. ...

  8. 2017.11.11 B201 练习题思路及解题方法

    2017.11.11 B201 练习题思路及解题方法 题目类型及涵盖知识点 本次总共有6道题目,都属于MISC分类的题目,涵盖的知识点有 信息隐藏 暴力破解 音轨,摩斯电码 gif修改,base64原 ...

  9. Notes of Daily Scrum Meeting(11.11)

    Notes of Daily Scrum Meeting(11.11) 今天是11月11号光棍节,不知道大家的购物热情被点燃没有,有没有买到自己心仪的东西.额,今天我们的团队任务进度和昨天差不多, 每 ...

  10. TeamWork#3,Week5,Scrum Meeting 11.6, 11.7, 11.11, 11.12

    11.6:到目前为止基本已完成相关知识的学习,各方面工作都开始进行,一开始进行比较慢. 11.7:项目遇到困难,需要补充相关知识,进度慢了下来. 11.11:各方面工作进展比较顺利,没有什么大问题. ...

随机推荐

  1. 【Qt开发】Qt5.7串口开发

    QT5有专门的串口类:  QSerialPort:提供访问串口的功能  QSerialPortInfo:提供系统中存在的串口的信息  具体使用方法:  1.在pro文件中加入: QT += seria ...

  2. 【嵌入式开发】树莓派h264实时视频监控

    FishXX之前用VLC串流输出视频,在电脑上需要VLC播放器.试了一下,感觉还是有点延时. 今天发现一个更加流畅,也不需要VLC播放器的树莓派远程视频监控方法,直接在浏览器中打开即可. 地址:htt ...

  3. [转帖]教你如何修改运行中的docker容器的端口映射

    教你如何修改运行中的docker容器的端口映射   在docker run创建并运行容器的时候,可以通过-p指定端口映射规则.但是,我们经常会遇到刚开始忘记设置端口映射或者设置错了需要修改.当dock ...

  4. MySQL -2- 体系结构-多实例模块

    0.在已创建mysql,port=3306的数据库前提下 需要删除/etc/.my.cnf再做以下操作 cp /etc/my.cnf /etc/my.cnf.3306 1.mkdir -p /u02/ ...

  5. ALS部署Spark集群入坑记

    [Stage 236:> (0 + 0) / 400]17/12/04 09:45:55 ERROR yarn.ApplicationMaster: User class threw excep ...

  6. Ubuntu16.04.1安装Caffe(GPU)

    Caffe的优势: 1.上手快:模型与相应优化均以文本形式而非代码形式给出,caffe给出了模型的定义,最优化设置以及预训练的权重 2.速度快:与CuDNN结合使用,测试AlexNet模型,在K40上 ...

  7. [Wpf]在C#中添加 collectionViewSource

    Products = new ObservableCollection<Product>(products); ProductOptions = new ObservableCollect ...

  8. RocketMQ高性能原理(pushConsumer,CommitLog,ZeroCopy)

    1. Rocketmq消费模型(实时性) 常见的数据同步方式有这几种: push:producer发送消息后,broker马上把消息投递给consumer.这种方式好在实时性比较高,但是会增加brok ...

  9. docker无法删除<none>镜像

    .进入root权限 sudo su # 或 sudo -i .停止所有的container(这样才能够删除其中的images): docker stop $(docker ps -a -q) 如果想要 ...

  10. 机器学习及scikit-learn

    一.机器学习以及scikit-learn 1. 机器学习基本步骤: (1)定义一系列函数  =>   (2)定义函数的优劣  =>  (3)选择最优函数 2.什么是scikit-learn ...