题目


正解

有个比较显然的思路是给特殊点划分到ccc个集合中(集合可以为空)。
先解决一个子问题:一条链,两端相同和两端不同的答案分别是什么。
这个东西可以简单递推,然后用矩阵乘法优化。
题解中有个结论:两端相同:(c−1)len+(−1)len(c-1)^{len}+(-1)^{len}(c−1)len+(−1)len;两端不同:(c−1)len+(−1)len+1(c−1)(c-1)^{len}+(-1)^{len+1}(c-1)(c−1)len+(−1)len+1(c−1)
不要问我为什么,我也不会证。

考虑一个集合中的每个点的贡献。钦定顺时针方向连边(计算链的贡献),每条边的贡献挂在始点处。于是对于一个点而言,如果它顺时针的下一个点和它同在一个集合内,那就有两端相同的贡献;如果不同在一个集合内,那就有两端不同的贡献。
贡献算完了,我们发现剩下的就是个子集卷积。子集卷积有个很经典的问题:如何保证或卷积的子集没有交?
一种方法是像昨天那题一样枚举划分。但是复杂度要乘上划分数,不划算(gmh77就是这么写了,TLE90分)。
介绍一种新的方法:
将[0,2k)[0,2^k)[0,2k)的数组FFF中,每个位置存一个多项式。FS=x∣S∣∗S的贡献F_S=x^{|S|}*S的贡献FS​=x∣S∣∗S的贡献。
这样在子集卷积的过程中,xxx的指数也在相加。这样子集大小始终是小于等于xxx的指数的。当子集大小等于xxx的指数的时候,不就是保证了子集之间没有交吗?
于是我们搞出这样的FFF,然后卷ccc次FFF,就可以搞到我们要的东西。

这样处理之后,对FFF做一遍FWTFWTFWT。由于FWTFWTFWT中没有多项式乘法,所以时间复杂度为O(k22k)O(k^2 2^k)O(k22k)。
接下来对每个位置求它的ccc次方。求ccc次方可以先lnlnln再expexpexp求。
这里kkk那么小写MTTMTTMTT肯定不划算。于是就有了O(k2)O(k^2)O(k2)暴力求lnlnln和expexpexp的方法:
考虑求expexpexp,设g(x)=ef(x)g(x)=e^{f(x)}g(x)=ef(x)
则g′(x)=ef(x)f′(x)=g(x)f′(x)g'(x)=e^{f(x)}f'(x)=g(x)f'(x)g′(x)=ef(x)f′(x)=g(x)f′(x)
可以推出ngn=∑i=1nifign−ing_n=\sum_{i=1}^nif_ig_{n-i}ngn​=∑i=1n​ifi​gn−i​
发现gng_ngn​是从g1..n−1g_{1..n-1}g1..n−1​推过来的,于是直接递推即可。
移项就可以得到lnlnln的递推式:nfn=gn=∑i=1n−1ifign−inf_n=g_n=\sum_{i=1}^{n-1}if_ig_{n-i}nfn​=gn​=∑i=1n−1​ifi​gn−i​
对2k2^k2k个多项式求乘方,时间复杂度O(k22k)O(k^2 2^k)O(k22k)。

搞完之后取出xkx^kxk项,然后做IFWTIFWTIFWT即可。由于我们只需要全集(即2k−12^k-12k−1)的答案,所以可以直接O(2k)O(2^k)O(2k)容斥得到。


代码

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cassert>
#define ll long long
#define K 20
#define mo 1000000007
ll qpow(ll x,ll y=mo-2){ll r=1;for (;y;y>>=1,x=x*x%mo)if (y&1)r=r*x%mo;return r;
}
ll inv[K+1];
ll n,c;
int k,m;
ll a[K],len[K];
int id[K],re[K];
bool cmpid(int x,int y){return a[x]<a[y];}
ll h[K][2];
struct Matrix{ll m[2][2];
};
void operator*=(Matrix &a,Matrix b){static Matrix c;for (int i=0;i<2;++i)for (int j=0;j<2;++j){ll sum=0;for (int k=0;k<2;++k)sum+=a.m[i][k]*b.m[k][j];c.m[i][j]=sum%mo;}memcpy(&a,&c,sizeof c);
}
void getpow(Matrix &x,ll y){static Matrix r;r={1,0,0,1};for (;y;y>>=1,x*=x)if (y&1)r*=x;memcpy(&x,&r,sizeof r);
}
void calc(ll n,ll f[]){static Matrix T;T={(c-2)%mo,1,(c-1)%mo,0};getpow(T,n);f[1]=1*T.m[1][1];//[0 1]*Tf[0]=1*T.m[0][1];//[1 0]*T
}
bool e[K][K];
int cnt[1<<K];
int dp[1<<K];
int f[1<<K][K+1],g[1<<K];
void fwt_or(int f[][K+1],int n){for (int i=1;i<1<<n;i<<=1)for (int j=0;j<1<<n;j+=i<<1)for (int k=j;k<j+i;++k)for (int t=0;t<=n;++t)(f[k+i][t]+=f[k][t])%=mo;
}
void getexp(int f[],int n){static int g[K+1];g[0]=1;for (int i=1;i<=n;++i){ll sum=0;for (int j=1;j<=i;++j)(sum+=(ll)j*f[j]%mo*g[i-j])%=mo;sum=sum*inv[i]%mo;g[i]=sum;}memcpy(f,g,sizeof(int)*(n+1));
}
void getln(int g[],int n){static int f[K+1];f[0]=0;for (int i=1;i<=n;++i){ll sum=0;for (int j=1;j<i;++j)(sum+=(ll)j*f[j]%mo*g[i-j])%=mo;sum=((ll)i*g[i]%mo-sum+mo)%mo*inv[i]%mo;f[i]=sum;}memcpy(g,f,sizeof(int)*(n+1));
}
int getpow(int f[],int n,ll c){getln(f,n);c%=mo;for (int i=0;i<=n;++i)f[i]=(ll)f[i]*c%mo;getexp(f,n);return f[n];
}
int main(){freopen("chess.in","r",stdin);freopen("chess.out","w",stdout);scanf("%lld%d%d%lld",&n,&k,&m,&c);for (int i=0;i<k;++i){scanf("%lld",&a[i]);--a[i];id[i]=i;}inv[1]=1;for (int i=2;i<=k;++i)inv[i]=(mo-mo/i)*inv[mo%i]%mo;sort(id,id+k,cmpid);for (int i=0;i<k;++i)re[id[i]]=i;for (int i=1;i<=m;++i){int u,v;scanf("%d%d",&u,&v);--u,--v;u=re[u],v=re[v];e[u][v]=e[v][u]=1;}sort(a,a+k);for (int i=0;i<k;++i){int j=(i+1)%k;len[i]=(a[j]-a[i]+n)%n;if (len[i]==1)e[i][j]=e[j][i]=1;calc(len[i],h[i]);}dp[0]=1;for (int i=0;i<k;++i)for (int s=0;s<1<<i;++s)if (dp[s]){bool ok=1;for (int t=0;t<k && ok;++t)if (s>>t&1 && e[i][t])ok=0;if (ok==0)continue;dp[s|1<<i]=1;}for (int s=0;s<1<<k;++s){cnt[s]=cnt[s>>1]+(s&1);if (dp[s]){ll pro=1;for (int i=0;i<k;++i)if (s>>i&1){int j=(i+1)%k;(pro*=h[i][s>>j&1])%=mo;}f[s][cnt[s]]=pro;}}fwt_or(f,k);for (int s=0;s<1<<k;++s)g[s]=getpow(f[s],k,c);ll ans=0;for (int s=0;s<1<<k;++s)ans+=(k-cnt[s]&1?-1:1)*g[s];ans=(ans%mo+mo)%mo;printf("%lld\n",ans);return 0;
}

6728. 【2020.06.16省选模拟】T2 战棋游戏相关推荐

  1. 6691. 【2020.06.05省选模拟】六道剑「一念无量劫」

    题目 一个排列,可以交换任意两个一次,或交换相邻两个无限次. 求排序的最少交换次数. n≤3e5n\leq 3e5n≤3e5 思考历程 显然可以先交换,再求冒泡排序. 先求出逆序对个数,然后问题转化为 ...

  2. JZOJ6693. 【2020.06.05省选模拟】紫色彼岸樱推迟绽放

    Description 幽幽子饿了,妖梦需要给幽幽子准备食物. 有 T 天,每天幽幽子划分成了 k 个时段,妖梦需要安排每一天的日程. 第 i 天妖梦准备了 D+i-1 道菜,每道菜有无数个.第 1 ...

  3. 6681. 【2020.06.02省选模拟】图

    题目 给出一个无重边.自环的平面图.需要回答若干个询问,每次询问给出一个简单环,求这个简单环形成的多边形内部有多少个点(包括边界上). n≤1e5,m≤3e5,Q≤3e5n\leq 1e5,m\leq ...

  4. 【NOIP模拟赛】战棋游戏

    战棋游戏 Description Rainbow擅长战棋类游戏.著名的战棋游戏有很多,例如<曹操传>.<瓦岗山异闻录>等.在本题中,我们考虑战棋游戏的一个简单版本,基于一下规则 ...

  5. NOIP2018 模拟测试 day1 战棋游戏

    题目: 战棋游戏 Rainbow 擅长玩战棋类游戏.著名的战棋游戏有很多,例如<曹操传>.<瓦岗 山异闻录>等.在本题中,我们考虑战棋游戏的一个简单版本,基于以下规则: ⚫ 地 ...

  6. NOI2019省选模拟赛 第五场

    爆炸了QAQ 传送门 \(A\) \(Mas\)的童年 这题我怎么感觉好像做过--我记得那个时候还因为没有取\(min\)结果\(100\to 0\)-- 因为是个异或我们肯定得按位考虑贡献了 把\( ...

  7. 纪中集训2020.01.16【NOIP普及组】模拟赛C组总结+【0.Matrix】分析

    纪中集训2020.01.16[NOIP普及组]模拟赛C组总结+[0.Matrix]分析 题目: 0.matrix 1.product 2.binary 3.value 巨佬估分:100+100+40+ ...

  8. 省选模拟赛记录(越往下越新哦~~~)

    LOG 模拟赛 第一次见尼玛这么给数据范围的-- 开考有点困,迷迷糊糊看完了三道题,真的是像老吕说的那样,一道都不会-- 思考T1,感觉有点感觉,但是太困了,就先码了暴力,发现打表可以50分,于是就大 ...

  9. 浙江大学软件学院2020年保研上机模拟练习

    浙江大学软件学院2020年保研上机模拟练习 7-1.Standard Form of Polynomial (20分) 7-2.Distance of Triples (25分) 7-3. Parti ...

最新文章

  1. Flex 容器基本概念
  2. 初始化列表||类对象作为类成员|| 静态成员
  3. priority_queue
  4. 仪表指针样式_Qt自定义Widget之仪表盘
  5. 前端必知必会--JSON.stringify()犀利的第三个参数
  6. html5 video 播放状态,10分钟了解HTML5的Video标签属性、方法和事件
  7. MySQL数据库优化技术概述
  8. shader 反射 水面_2D水面波光效果,以及一些2D常用shader的实现
  9. 【UWP】批量修改图标尺寸
  10. 中国计量学院全国计算机二级报名,中国计量大学教务管理系统入口https://jwc.cjlu.edu.cn/...
  11. 提升效率小工具,我用30分钟就干完一天的活
  12. 用OpenCV创建第一个图像
  13. 巨杉数据库入选2021年广州独角兽创新企业榜单
  14. Mac下载工具哪个好?迅雷 for Mac是个不错的选择!
  15. 深度学习CNN算法原理
  16. ICM-20602 IMU ACCEL/GYRO/TEMP I2C/SPI LGA
  17. 解决Namecheap域名转入确认邮件重发及邮件收不到
  18. 初中文化能学python吗_初中文化可以学Python编程吗,我想通过这个渠道进入人工智能这个大行业?...
  19. html 图片右侧空白,CSS缩小窗口时,背景图出现右侧空白
  20. ThinkPad E450 拆机换电池

热门文章

  1. 20个热门少儿编程网站与应用【家长必读】
  2. Geospatial
  3. 一分钟教会你如何做自媒体淘客
  4. 度假式联合办公是创业者流行的新工作方式
  5. 关于输入法的弹出与关闭
  6. IDM6.41最新版下载器Internet Download Manager
  7. 铁路虚拟服务器,12306内部多图大揭秘:竟然是这个样子
  8. 第七次网页前端培训笔记(JS对象和事件)
  9. 浅谈整数拆分的四种方法
  10. 学习Javascript之数组去重