CodeCraft-19 and Codeforces Round #537 (Div. 2) 题解
D. Destroy the Colony
首先明确题意:除了规定的两种(或一种)字母要在同侧以外,其他字母也必须在同侧。
发现当每种字母在左/右边确定之后,方案数就确定了,就是分组的方案数乘\(\frac{((n/2)!)^2}{\prod cnt_i!}\)。
分组的方案数考虑DP,设\(dp_{i,j}\)为前\(i\)个字母,占了左边\(j\)个位置的方案数,则有:
\]
当\(i\)是指定字母时特判即可。
这样复杂度为\(O(52^3n)\),无法通过。
考虑最多指定两次字母,而且字母顺序对结果没有关系,可以先把所有的DP出来,然后假装指定的两个字母是最后两个DP的,按照DP方程撤销即可。
#include<bits/stdc++.h>
clock_t t=clock();
namespace my_std{
using namespace std;
#define pii pair<int,int>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define templ template<typename T>
#define sz 101101
#define mod 1000000007
typedef long long ll;
typedef double db;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
templ inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
templ inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
templ inline void read(T& t)
{
t=0;char f=0,ch=getchar();double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
t=(f?-t:t);
}
template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
char __sr[1<<21],__z[20];int __C=-1,__Z=0;
inline void Ot(){fwrite(__sr,1,__C+1,stdout),__C=-1;}
inline void print(register int x)
{
if(__C>1<<20)Ot();if(x<0)__sr[++__C]='-',x=-x;
while(__z[++__Z]=x%10+48,x/=10);
while(__sr[++__C]=__z[__Z],--__Z);__sr[++__C]='\n';
}
void file()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
}
inline void chktime()
{
#ifndef ONLINE_JUDGE
cout<<(clock()-t)/1000.0<<'\n';
#endif
}
#ifdef mod
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
ll inv(ll x){return ksm(x,mod-2);}
#else
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
#endif
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std;
int n,m,K;
char s[sz];
int a[sz],aa[sz];
int cnt[233];
ll T;
ll fac[sz],_fac[sz];
void init(){fac[0]=_fac[0]=1;rep(i,1,sz-1) fac[i]=fac[i-1]*i%mod,_fac[i]=inv(fac[i]);}
ll C(int n,int m){return n>=m&&m>=0?fac[n]*_fac[m]%mod*_fac[n-m]%mod:0;}
int sum[66];
ll dp[sz],cur[sz];
ll ans[66][66];
void Init()
{
rep(i,1,K) sum[i]=sum[i-1]+cnt[i];
dp[0]=1;
int n=::n>>1;
rep(i,1,K)
drep(j,n,cnt[i])
dp[j]=(dp[j]+dp[j-cnt[i]])%mod;
}
ll solve(int x,int y)
{
int n=::n>>1;
if ((cnt[x]>n&&x==y)||(cnt[x]+cnt[y]>n&&x!=y)) return 0;
ll c=fac[n]*fac[n]%mod*inv(T)%mod;
if (x==y) return c*dp[n]%mod;
rep(i,0,n) cur[i]=dp[i];
rep(j,cnt[x],n)
cur[j]=(cur[j]-cur[j-cnt[x]]+mod)%mod;
rep(j,cnt[y],n)
cur[j]=(cur[j]-cur[j-cnt[y]]+mod)%mod;
return c*cur[n-cnt[x]-cnt[y]]*2%mod;
}
int main()
{
file();
cin>>(s+1);n=strlen(s+1);
rep(i,1,n) a[i]=aa[i]=s[i];
sort(aa+1,aa+n+1);K=unique(aa+1,aa+n+1)-aa-1;
rep(i,1,n) a[i]=lower_bound(aa+1,aa+K+1,a[i])-aa;
rep(i,1,n) ++cnt[a[i]];
init();Init();
T=1;rep(i,1,K) T=T*fac[cnt[i]]%mod;
rep(i,1,K) rep(j,1,K) ans[i][j]=solve(i,j);
read(m);
int x,y;
while (m--) read(x,y),printf("%lld\n",ans[a[x]][a[y]]);
return 0;
}
E. Tree
显然需要DP,但怎么DP呢?
考虑每个点只被自己的祖先限制,可以把要DP的点按某种方法排序,使得每个点的祖先都在自己之前处理完毕,就可以了。
设\(dp_{i,j}\)表示前\(i\)个点,分成\(j\)个集合的方案数,则有:
\]
其中\(f_x\)表示\(x\)的祖先数。
这时又发现按\(f_x\)从小到大排序,就可以满足要求,于是就做完了。
注意出题人卡空间,DP需要滚掉一维。
#include<bits/stdc++.h>
clock_t t=clock();
namespace my_std{
using namespace std;
#define pii pair<int,int>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define templ template<typename T>
#define sz 101010
#define mod 1000000007
typedef long long ll;
typedef double db;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
templ inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
templ inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
templ inline void read(T& t)
{
t=0;char f=0,ch=getchar();double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
t=(f?-t:t);
}
template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
inline void print(register int x)
{
if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
void file()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
}
inline void chktime()
{
#ifndef ONLINE_JUDGE
cout<<(clock()-t)/1000.0<<'\n';
#endif
}
#ifdef mod
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
ll inv(ll x){return ksm(x,mod-2);}
#else
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
#endif
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std;
int n,Q;
struct hh{int t,nxt;}edge[sz<<1];
int head[sz],ecnt;
void make_edge(int f,int t)
{
edge[++ecnt]=(hh){t,head[f]};
head[f]=ecnt;
edge[++ecnt]=(hh){f,head[t]};
head[t]=ecnt;
}
int dfn[sz],son[sz],size[sz],dep[sz],top[sz],fa[sz],T;
#define v edge[i].t
void dfs1(int x,int fa)
{
::fa[x]=fa;dep[x]=dep[fa]+1;
size[x]=1;
go(x) if (v!=fa)
{
dfs1(v,x);
size[x]+=size[v];
if (size[v]>size[son[x]]) son[x]=v;
}
}
void dfs2(int x,int fa,int tp)
{
top[x]=tp;dfn[x]=++T;
if (son[x]) dfs2(son[x],x,tp);
go(x) if (v!=fa&&v!=son[x]) dfs2(v,x,v);
}
#undef v
int tr[sz];
void add(int x,int y){while (x<=n) tr[x]+=y,x+=(x&(-x));}
int query(int x){int ret=0;while (x) ret+=tr[x],x-=(x&(-x));return ret;}
int query(int x,int y){return query(y)-query(x-1);}
int Query(int x,int y)
{
int ret=0;
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) swap(x,y);
ret+=query(dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
ret+=query(dfn[x],dfn[y]);
return ret;
}
int a[sz];
int f[sz];
inline bool cmp(const int &x,const int &y){return f[x]<f[y];}
ll dp[333];
int main()
{
file();
int x,y,K,m,rt;
read(n,Q);
rep(i,1,n-1) read(x,y),make_edge(x,y);
dfs1(1,0);dfs2(1,0,1);
while (Q--)
{
read(K,m,rt);
rep(i,1,K) read(a[i]),add(dfn[a[i]],1);
rep(j,1,m) dp[j]=0;
dp[0]=1;
rep(i,1,K) f[a[i]]=Query(rt,a[i])-1;
sort(a+1,a+K+1,cmp);
rep(i,1,K)
{
x=a[i];
drep(j,m,f[x]+1) dp[j]=(dp[j-1]+dp[j]*(j-f[x])%mod)%mod;
rep(j,0,f[x]) dp[j]=0;
}
ll ans=0;
rep(i,1,m) (ans+=dp[i])%=mod;
printf("%lld\n",ans);
rep(i,1,K) add(dfn[a[i]],-1);
}
return 0;
}
CodeCraft-19 and Codeforces Round #537 (Div. 2) 题解的更多相关文章
- Codeforces Round #182 (Div. 1)题解【ABCD】
Codeforces Round #182 (Div. 1)题解 A题:Yaroslav and Sequence1 题意: 给你\(2*n+1\)个元素,你每次可以进行无数种操作,每次操作必须选择其 ...
- Codeforces Round #608 (Div. 2) 题解
目录 Codeforces Round #608 (Div. 2) 题解 前言 A. Suits 题意 做法 程序 B. Blocks 题意 做法 程序 C. Shawarma Tent 题意 做法 ...
- Codeforces Round #525 (Div. 2)题解
Codeforces Round #525 (Div. 2)题解 题解 CF1088A [Ehab and another construction problem] 依据题意枚举即可 # inclu ...
- Codeforces Round #528 (Div. 2)题解
Codeforces Round #528 (Div. 2)题解 A. Right-Left Cipher 很明显这道题按题意逆序解码即可 Code: # include <bits/stdc+ ...
- Codeforces Round #466 (Div. 2) 题解940A 940B 940C 940D 940E 940F
Codeforces Round #466 (Div. 2) 题解 A.Points on the line 题目大意: 给你一个数列,定义数列的权值为最大值减去最小值,问最少删除几个数,使得数列的权 ...
- Codeforces Round #677 (Div. 3) 题解
Codeforces Round #677 (Div. 3) 题解 A. Boring Apartments 题目 题解 简单签到题,直接数,小于这个数的\(+10\). 代码 #include &l ...
- Codeforces Round #665 (Div. 2) 题解
Codeforces Round #665 (Div. 2) 题解 写得有点晚了,估计都官方题解看完切掉了,没人看我的了qaq. 目录 Codeforces Round #665 (Div. 2) 题 ...
- Codeforces Round #160 (Div. 1) 题解【ABCD】
Codeforces Round #160 (Div. 1) A - Maxim and Discounts 题意 给你n个折扣,m个物品,每个折扣都可以使用无限次,每次你使用第i个折扣的时候,你必须 ...
- Codeforces Round #383 (Div. 2) 题解【ABCDE】
Codeforces Round #383 (Div. 2) A. Arpa's hard exam and Mehrdad's naive cheat 题意 求1378^n mod 10 题解 直接 ...
随机推荐
- ****** 四十九 ******、软设笔记【UML分析和意义】-建模的意义,UML的特点、结构,用例图
UML UML又称同一建模语言或标准建模语言,是一个支持模型化和软件系统开发的图形化语言,它的作用域不仅支持面向对象的分析与设计,还支持从需求分析开始的软件开发的全过程. 建模的意义: 模型是对现实的 ...
- Java--- Ambiguous mapping. Cannot map "***Controller" been method解决办法
打开网页报错: Ambiguous mapping. Cannot map 'handController' method public com.smallchill.core.toolbox.aj ...
- Spring 快速开始 Profile 和 Bean
和maven profile类似,Spring bean definition profile 有两个组件:声明和激活. [栗子:开发测试环境使用HyperSQL 生产环境使用JNDI上下文根据配置查 ...
- webwork框架
以前都没有用过WebWork这个框架,只是听说过.没想到现在要用,所以就自学了一下.做了个小例子给大家分享下中间遇到的苦难和经验. 准备工作:首先要去下载WebWork框架的开发包.我用的2.2.6版 ...
- Python 爬虫二 requests模块
requests模块 Requests模块 get方法请求 整体演示一下: import requests response = requests.get("https://www.baid ...
- MySQL基本命令(待更新...)
数据库操作SQL语句 show databases; 表操作SQL语句 数据库权限操作SQL语句 参考链接 :http://www.cnblogs.com/bzys/archive/2013/01/2 ...
- Python概念(八)字符串格式化:%和.format
https://www.cnblogs.com/nulige/p/6115793.html
- zabbix系列~mysql进行监控
一 简介:zabbix进行数据库监控 二 目的:采用percona进行插件式安装监控 三 安装 环境 zabbix_agent 步骤 yum -y install php php-mysql yum ...
- 图片转换base64编码,点击div的时候选择文件
有时候我们希望文件上传的时候预览图片,下面插件可以实现上传前预览图片 (也可以提取文件的base64编码) max-height: 140px;max-width: 120px;可以指定图片的最大宽度 ...
- 【SVN】SVN初识
SVN 介绍 SVN是Subversion的简称,是一个开放源代码的版本控制系统,相较于RCS.CVS,它采用了分支管理系统,它的设计目标就是取代CVS.互联网上很多版本控制服务已从CVS迁移到Sub ...