【XSY1519】彩灯节 DP 数学 第二类斯特林数
题目大意
有\(n\)盏灯,\(m\)个限制。每个限制\((x,y)\)表示第\(x\)盏灯与第\(y\)盏灯之间必须且只能亮一盏。
记一种情况\(x\)亮着的灯的数量为\(f_x\),求\(\sum {(f_x)}^k\)
\(n\leq 200000,k\leq 100\)
题解
我们先把整张图黑白染色。
如果不是二分图就无解。
我们发现两个不同的联通分量的灯的状态是没有关系的。
我们可以考虑DP:
\(f_{i,j}=\)前\(i\)个联通分量中亮的彩灯个数的\(j\)次方和
\(a_{i,j}=\)第\(i\)个联通分量中亮的彩灯个数的\(j\)次方和
根据二项式定理\({(a+b)}^n=\sum_{i=0}^n\binom nia^ib^{n-i}\)有:
\]
\]
\]
观察到\(p=1004535809\)是一个NTT模数(原根为\(3\)),所以可以用NTT加速。
没了
时间复杂度:\(O(nk\log k)\)
题解2
FFT很明显会TLE
有一个公式:
\]
后面两个东西很容易算,只用考虑第一个怎么求
这不就是个组合数吗
直接DP就行了。
时间复杂度:\(O(nk)\)
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
ll p=1004535809;
ll fp(ll a,ll b)
{
ll s=1;
while(b)
{
if(b&1)
s=s*a%p;
a=a*a%p;
b>>=1;
}
return s;
}
namespace ntt
{
int N;
ll w1[500010];
ll w2[500010];
int rev[500010];
void get(int n)
{
N=1;
while(N<n)
N<<=1;
int i;
for(i=2;i<=N;i++)
{
w1[i]=fp(3,(p-1)/i);
w2[i]=fp(w1[i],p-2);
}
rev[0]=0;
for(i=1;i<N;i++)
rev[i]=(rev[i>>1]>>1)|(i&1?N>>1:0);
}
void ntt(ll *a,int t)
{
int i,j,k;
ll u,v,w,wn;
for(i=0;i<N;i++)
if(rev[i]<i)
swap(a[i],a[rev[i]]);
for(i=2;i<=N;i<<=1)
{
wn=t?w1[i]:w2[i];
for(j=0;j<N;j+=i)
{
w=1;
for(k=j;k<j+i/2;k++)
{
u=a[k];
v=a[k+i/2]*w%p;
a[k]=(u+v)%p;
a[k+i/2]=(u-v+p)%p;
w=w*wn%p;
}
}
}
if(!t)
{
ll inv=fp(N,p-2);
for(i=0;i<N;i++)
a[i]=a[i]*inv%p;
}
}
}
struct list
{
int v[500010];
int t[500010];
int h[200010];
int n;
list()
{
n=0;
memset(h,0,sizeof h);
}
void add(int x,int y)
{
n++;
v[n]=y;
t[n]=h[x];
h[x]=n;
}
};
list l;
int vis[200010];
void failed()
{
putchar('0');
exit(0);
}
int s1,s2;
void dfs(int x,int fa,int v)
{
vis[x]=v;
if(v)
s1++;
else
s2++;
int i;
for(i=l.h[x];i;i=l.t[i])
if(l.v[i]!=fa)
{
if(vis[l.v[i]]==-1)
dfs(l.v[i],x,v^1);
else if(vis[l.v[i]]==vis[x])
failed();
}
}
ll f[500010];
ll a[500010];
int n,m,k;
ll fac[500010];
int main()
{
freopen("bulb.in","r",stdin);
freopen("bulb.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
ntt::get(2*(k+1));
int i,j,x,y;
fac[0]=1;
for(i=1;i<=1000;i++)
fac[i]=fac[i-1]*i%p;
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
l.add(x,y);
l.add(y,x);
}
memset(vis,-1,sizeof vis);
f[0]=1;
for(i=1;i<=n;i++)
if(vis[i]==-1)
{
s1=s2=0;
dfs(i,0,1);
for(j=0;j<=k;j++)
a[j]=(fp(s1,j)+fp(s2,j))%p;
for(j=k+1;j<ntt::N;j++)
a[j]=f[j]=0;
for(j=0;j<ntt::N;j++)
{
ll inv=fp(fac[j],p-2);
a[j]=a[j]*inv%p;
f[j]=f[j]*inv%p;
}
ntt::ntt(a,1);
ntt::ntt(f,1);
for(j=0;j<ntt::N;j++)
f[j]=f[j]*a[j]%p;
ntt::ntt(f,0);
for(j=0;j<=k;j++)
f[j]=f[j]*fac[j]%p;
// do something here ...
}
printf("%lld\n",f[k]);
return 0;
}
代码2
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
ll p=1004535809;
ll fp(ll a,ll b)
{
ll s=1;
while(b)
{
if(b&1)
s=s*a%p;
a=a*a%p;
b>>=1;
}
return s;
}
struct list
{
int v[500010];
int t[500010];
int h[200010];
int n;
list()
{
n=0;
memset(h,0,sizeof h);
}
void add(int x,int y)
{
n++;
v[n]=y;
t[n]=h[x];
h[x]=n;
}
};
list l;
int vis[200010];
void failed()
{
putchar('0');
exit(0);
}
int s1,s2;
void dfs(int x,int fa,int v)
{
vis[x]=v;
if(v)
s1++;
else
s2++;
int i;
for(i=l.h[x];i;i=l.t[i])
if(l.v[i]!=fa)
{
if(vis[l.v[i]]==-1)
dfs(l.v[i],x,v^1);
else if(vis[l.v[i]]==vis[x])
failed();
}
}
int n,m,k;
ll fac[500010];
ll f[510];
ll f2[510];
ll f1[510];
void dp1()
{
int i;
for(i=k;i>=1;i--)
f1[i]=(f1[i]+f1[i-1])%p;
}
void dp2()
{
int i;
for(i=k;i>=1;i--)
f2[i]=(f2[i]+f2[i-1])%p;
}
ll s[510][510];
int main()
{
// freopen("bulb.in","r",stdin);
// freopen("bulb4.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
int i,j,x,y;
fac[0]=1;
for(i=1;i<=1000;i++)
fac[i]=fac[i-1]*i%p;
s[0][0]=1;
for(i=1;i<=100;i++)
{
s[i][0]=0;
for(j=1;j<=100;j++)
s[i][j]=(s[i-1][j-1]+s[i-1][j]*j%p)%p;
}
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
l.add(x,y);
l.add(y,x);
}
memset(vis,-1,sizeof vis);
f[0]=1;
for(i=1;i<=n;i++)
if(vis[i]==-1)
{
s1=s2=0;
dfs(i,0,1);
for(j=0;j<=k;j++)
f1[j]=f2[j]=f[j];
for(j=1;j<=s1;j++)
dp1();
for(j=1;j<=s2;j++)
dp2();
for(j=0;j<=k;j++)
f[j]=(f1[j]+f2[j])%p;
}
ll ans=0;
for(i=0;i<=k;i++)
ans=(ans+f[i]*s[k][i]%p*fac[i]%p)%p;
printf("%lld\n",ans);
return 0;
}
【XSY1519】彩灯节 DP 数学 第二类斯特林数的更多相关文章
- 【hdu4045】Machine scheduling(dp+第二类斯特林数)
传送门 题意: 从\(n\)个人中选\(r\)个出来,但每两个人的标号不能少于\(k\). 再将\(r\)个人分为不超过\(m\)个集合. 问有多少种方案. 思路: 直接\(dp\)预处理出从\(n\ ...
- HDU - 4625 JZPTREE(第二类斯特林数+树DP)
https://vjudge.net/problem/HDU-4625 题意 给出一颗树,边权为1,对于每个结点u,求sigma(dist(u,v)^k). 分析 贴个官方题解 n^k并不好转移,于是 ...
- bzoj 2159 Crash 的文明世界 && hdu 4625 JZPTREE ——第二类斯特林数+树形DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2159 学习材料:https://blog.csdn.net/litble/article/d ...
- P4827 [国家集训队] Crash 的文明世界(第二类斯特林数+树形dp)
传送门 对于点\(u\),所求为\[\sum_{i=1}^ndis(i,u)^k\] 把后面那堆东西化成第二类斯特林数,有\[\sum_{i=1}^n\sum_{j=0}^kS(k,j)\times ...
- Codeforces Round #100 E. New Year Garland (第二类斯特林数+dp)
题目链接: http://codeforces.com/problemset/problem/140/E 题意: 圣诞树上挂彩球,要求从上到下挂\(n\)层彩球.已知有\(m\)种颜色的球,球的数量不 ...
- 国家集训队 Crash 的文明世界(第二类斯特林数+换根dp)
题意 题目链接:https://www.luogu.org/problem/P4827 给定一棵 \(n\) 个节点的树和一个常数 \(k\) ,对于树上的每一个节点 \(i\) ,求出 \( ...
- BZOJ 2159: Crash 的文明世界(组合数学+第二类斯特林数+树形dp)
传送门 解题思路 比较有意思的一道数学题.首先\(n*k^2\)的做法比较好想,就是维护一个\(x^i\)这种东西,然后转移的时候用二项式定理拆开转移.然后有一个比较有意思的结论就是把求\(x^i\) ...
- [题解] LOJ 3300 洛谷 P6620 [省选联考 2020 A 卷] 组合数问题 数学,第二类斯特林数,下降幂
题目 题目里要求的是: \[\sum_{k=0}^n f(k) \times X^k \times \binom nk \] 这里面出现了给定的多项式,还有组合数,这种题目的套路就是先把给定的普通多项 ...
- 【BZOJ2159】Crash的文明世界(第二类斯特林数,动态规划)
[BZOJ2159]Crash的文明世界(第二类斯特林数,动态规划) 题面 BZOJ 洛谷 题解 看到\(k\)次方的式子就可以往二项式的展开上面考,但是显然这样子的复杂度会有一个\(O(k^2)\) ...
随机推荐
- 1076E - Vasya and a Tree(图的遍历)
题意:给出一棵根节点为1的树,执行m次修改操作,每次修改为a,b,c,表示a节点的子树中,距离a小于等于b的子节点的权值加上c,求m次操作后每个节点的权值 分析:用线段树维护每层节点的权值,然后dfs ...
- 2018 Multi-University Training Contest 2
题目链接:2018 Multi-University Training Contest 2 6318 Swaps and Inversions 题意:sum=x*逆序个数+交换次数*y,使sum最小 ...
- Comet OJ 热身赛(K题)principal(括号匹配问题+stack模拟)
principal 已经提交 已经通过 23.66% Total Submission:131 Total Accepted:31 题目描述 阿尔比恩王国潜伏着代号白鸽队''的一群间谍.在没有任务的时 ...
- latex 图片标题居中
1.有一个全局图片标题居中的方法: \usepackage[justification=centering]{caption} 2.如果排版时有的图标题想左对齐,有的想居中,前一个方法就不好了,这里可 ...
- 如何使用RSS
(转载: http://www.ruanyifeng.com/blog/2006/01/rss.html) 一. 自从我发现很多人不知道什么是RSS以后,我就一直想向大家介绍它,因为它太有用了,将来会 ...
- Freemarker 页面静态化技术使用入门案例
在访问 新闻.活动.商品 详情页面时, 路径可以是 xx[id].html, 服务器端根据请求 id, 动态生成 html 网页,下次访问数据时,无需再查询数据,直接将 html 静态页面返回.这样一 ...
- mybatis源码分析(四)---------------代理对象的生成
在mybatis两种开发方式这边文章中,我们提到了Mapper动态代理开发这种方式,现在抛出一个问题:通过sqlSession.getMapper(XXXMapper.class)来获取代理对象的过程 ...
- 在linux上安装Scala详细步骤
scala在linux安装很简单,就是下载,解压,配置环境变量,source一下成功. 提君博客原创 >>提君博客原创 http://www.cnblogs.com/tijun/ < ...
- springboot 如何操作redis
1.首先应该引入 依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactI ...
- python爬虫之git的安装
一.初始 1.发展历史 *最开始没有对代码的管理,导致很多东西混乱和丢失. *后来大家想了一个办法,用最简单最笨的方法,各种复制文件夹. *然后就出现了版本控制的工具. 1.单机版:RCS(198 ...