【XSY1519】彩灯节 DP 数学 第二类斯特林数

时间:2023-02-04 08:54:19

题目大意

​  有\(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}\)有:

\[f_{i,j}=\sum_{k=0}^{j}\binom{j}{k} a_{i-1,k}\times f_{i-1,j-k}
\]

\[=\sum_{k=0}^{j}\frac{j!}{k!(j-k)!}a_{i-1,k}\times f_{i-1,j-k}
\]

\[=j!\sum_{k=0}^{j}\frac{a_{i-1,k}}{k!}\times \frac{f_{i-1,j-k}}{(j-k)!}
\]

​  观察到\(p=1004535809\)是一个NTT模数(原根为\(3\)),所以可以用NTT加速。

​  没了

​  时间复杂度:\(O(nk\log k)\)

题解2

​  FFT很明显会TLE

​  有一个公式:

\[m^n=\sum_{k=0}^m\binom{m}{k}S(n,k)k!
\]

​  后面两个东西很容易算,只用考虑第一个怎么求

​  这不就是个组合数吗

​  直接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 数学 第二类斯特林数的更多相关文章

  1. 【hdu4045】Machine scheduling(dp&plus;第二类斯特林数)

    传送门 题意: 从\(n\)个人中选\(r\)个出来,但每两个人的标号不能少于\(k\). 再将\(r\)个人分为不超过\(m\)个集合. 问有多少种方案. 思路: 直接\(dp\)预处理出从\(n\ ...

  2. HDU - 4625 JZPTREE(第二类斯特林数&plus;树DP)

    https://vjudge.net/problem/HDU-4625 题意 给出一颗树,边权为1,对于每个结点u,求sigma(dist(u,v)^k). 分析 贴个官方题解 n^k并不好转移,于是 ...

  3. bzoj 2159 Crash 的文明世界 &amp&semi;&amp&semi; hdu 4625 JZPTREE ——第二类斯特林数&plus;树形DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2159 学习材料:https://blog.csdn.net/litble/article/d ...

  4. P4827 &lbrack;国家集训队&rsqb; Crash 的文明世界(第二类斯特林数&plus;树形dp)

    传送门 对于点\(u\),所求为\[\sum_{i=1}^ndis(i,u)^k\] 把后面那堆东西化成第二类斯特林数,有\[\sum_{i=1}^n\sum_{j=0}^kS(k,j)\times ...

  5. Codeforces Round &num;100 E&period; New Year Garland &lpar;第二类斯特林数&plus;dp&rpar;

    题目链接: http://codeforces.com/problemset/problem/140/E 题意: 圣诞树上挂彩球,要求从上到下挂\(n\)层彩球.已知有\(m\)种颜色的球,球的数量不 ...

  6. 国家集训队 Crash 的文明世界(第二类斯特林数&plus;换根dp)

    题意 ​ 题目链接:https://www.luogu.org/problem/P4827 ​ 给定一棵 \(n\) 个节点的树和一个常数 \(k\) ,对于树上的每一个节点 \(i\) ,求出 \( ...

  7. BZOJ 2159&colon; Crash 的文明世界&lpar;组合数学&plus;第二类斯特林数&plus;树形dp&rpar;

    传送门 解题思路 比较有意思的一道数学题.首先\(n*k^2\)的做法比较好想,就是维护一个\(x^i\)这种东西,然后转移的时候用二项式定理拆开转移.然后有一个比较有意思的结论就是把求\(x^i\) ...

  8. 【BZOJ2159】Crash的文明世界(第二类斯特林数,动态规划)

    [BZOJ2159]Crash的文明世界(第二类斯特林数,动态规划) 题面 BZOJ 洛谷 题解 看到\(k\)次方的式子就可以往二项式的展开上面考,但是显然这样子的复杂度会有一个\(O(k^2)\) ...

  9. Gym - 101147G G - The Galactic Olympics —— 组合数学 - 第二类斯特林数

    题目链接:http://codeforces.com/gym/101147/problem/G G. The Galactic Olympics time limit per test 2.0 s m ...

随机推荐

  1. OpenStack Havana 部署在Ubuntu 12&period;04 Server 【OVS&plus;GRE】——序

    OpenStack Havana 部署在Ubuntu 12.04 Server [OVS+GRE](一)——控制节点的安装 OpenStack Havana 部署在Ubuntu 12.04 Serve ...

  2. trailingZeroes

    Given an integer n, return the number of trailing zeroes in n!. 给一个数字n,返回它n!数字后面有多少个0. public class ...

  3. 新浪授权认证&lpar;不用SDK&rpar;

    微博开放平台:http://open.weibo.com/ 微博开放接口的调用,如发微博.关注等,都是需要获取用户身份认证的.目前微博开放平台用户身份鉴权主要采用的是OAuth2.0.另外,为了方便开 ...

  4. Windows下caffe的配置和调用caffe库(二)

    二. Caffe库的调用: 新建空白项目,将配置管理器更改为x64运行方式.(release和Debug均可). Debug配置: 1)      包含目录: D:\caffe-master\incl ...

  5. 用java语言写一个简易版本的登录页面,包含用户注册、用户登录、用户注销、修改密码等功能

    package com.Summer_0421.cn; import java.util.Arrays; import java.util.Scanner; /** * @author Summer ...

  6. SharePoint Set-SPUser 命令拒绝访问

    · 前言 最近碰到一个问题,由于User Profile Service服务有问题,用户信息无法更新.所以,想到Set-SPUser命令可以更新,于是乎找到这个命令,但是更新的时候发现拒绝访问的错误. ...

  7. spring学习笔记 星球日two - 注解方式配置bean

    注解要放在要注解的对象的上方 @Autowired private Category category; <?xml version="1.0" encoding=&quot ...

  8. Jquery实现可拖拽的树菜单

    效果图例如以下所看到的:下载地址http://download.csdn.net/detail/javaquentin/8290417 <html xmlns="http://www. ...

  9. 理解collate Chinese&lowbar;PRC&lowbar;CI&lowbar;AS

    我们在create table时经常会碰到这样的语句,例如:password nvarchar(10)collate chinese_prc_ci_as null,那它到底是什么意思呢?不妨看看下面: ...

  10. Jquery二维码在线生成(不能生成图片文件)

    附件地址:http://files.cnblogs.com/files/harxingxing/jQuery%E4%BA%8C%E7%BB%B4%E7%A0%81%E5%9C%A8%E7%BA%BF% ...