Description

 Solution

T1 shopping

目测是插板法乱搞一下

发现题解写的是容斥dp:

\[ans = \sum_i (-1)^ig[i]
\]

\(g[i]\)表示的有\(i\)个商店必然达到上限的方案数

考虑转化,设\(f[i][j]\)表示前\(i\)个商店,必然超过限制的商店的(上限+1)的和是\(j\)

\[f[i][j]=f[i-1][j]-f[i-1][j-w[i]-1]
\]

所以答案就可以这样计算:

\[ans=\sum_i f[n][i] C(k+n-1,n-1)
\]

后面那一块就是插板法

/*容斥dp */
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int MN=5e6+5,MM=301,mod=1e9+7;
int n,m,k,wi[MM],f[2][MM*MM+MN],fac[MN<<1],inv[MN<<1];
int C(int x,int y){if(y<=0)return 1;return 1ll*fac[x]*inv[y]%mod*inv[x-y]%mod;}
int fpow(int x,int M){int r=1;for(;M;M>>=1,x=1ll*x*x%mod)if(M&1)r=1ll*r*x%mod;return r;}
int main()
{
register int i,j,qz=0,ans=0;
n=read(),m=read(),k=read();
for(i=1;i<=m;++i) wi[i]=read(),qz+=wi[i];
for(fac[0]=i=1;i<=n+k;++i)fac[i]=1ll*fac[i-1]*i%mod;
for(inv[n+k]=fpow(fac[n+k],mod-2),i=n+k-1;~i;--i)inv[i]=1ll*inv[i+1]*(i+1)%mod;
f[1][wi[1]+1]=mod-1;f[1][0]=1;
for(i=2;i<=m;++i)
{
for(j=0;j<=qz+m;++j)
{
int l=j-wi[i]-1;f[i&1][j]=f[(i&1)^1][j];
if(l>=0) f[i&1][j]+=mod-f[(i&1)^1][l],f[i&1][j]%=mod;
}
}
for(i=0;i<=k;++i)ans+=1ll*f[m&1][i]*C(k+n-i-1,n-1)%mod,ans%=mod;
printf("%d\n",ans);
}

T2 highway

发现\(n\)很小,所以对于已经按照边权排号序的边集,求\(Kruskal\)生成森林的只要\(O(\alpha(n)n)\)

考虑线段树维护区间,每个节点保存用到的边(有序的),合并的时候做一次\(Kruskal\)即可

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
#define reg register
const int MN=105,MM=1e5+5;
int n,m,q;
struct edge{int u,v,w;}e[MM];
struct Node
{
vector<int> ed;
int val;
Node(){ed.clear();val=0;}
}T[MM<<2];
int fa[MN];
int getf(int x){return x==fa[x]?x:fa[x]=getf(fa[x]);}
bool union_(int x,int y){x=getf(x);y=getf(y);if(x==y)return false;fa[x]=y;return true;}
Node merge(Node x,Node y)
{
reg int si=x.ed.size(),sj=y.ed.size(),i,j;
for(i=1;i<=n;++i) fa[i]=i;
#define J y.ed[j]
#define I x.ed[i]
Node r;
for(i=0,j=0;i<si||j<sj;)
{
if(i==si||(j!=sj&&e[J].w<e[I].w))
{
if(union_(e[J].u,e[J].v)) r.ed.push_back(J),r.val+=e[J].w;
++j;continue;
}
if(union_(e[I].u,e[I].v)) r.ed.push_back(I),r.val+=e[I].w;
++i;
}
return r;
}
void build(int x,int l,int r)
{
if(l==r){T[x].ed.push_back(l);T[x].val=e[l].w;return;}
int mid=(l+r)>>1;
build(x<<1,l,mid);build(x<<1|1,mid+1,r);
T[x]=merge(T[x<<1],T[x<<1|1]);
}
Node query(int x,int l,int r,int a,int b)
{
if(l==a&&r==b) return T[x];
int mid=(l+r)>>1;
if(b<=mid) return query(x<<1,l,mid,a,b);
if(a>mid) return query(x<<1|1,mid+1,r,a,b);
else return merge(query(x<<1,l,mid,a,mid),query(x<<1|1,mid+1,r,mid+1,b));
}
int main()
{
n=read();m=read();q=read();
reg int i,l,r;
for(i=1;i<=m;++i) e[i].u=read(),e[i].v=read(),e[i].w=read();
build(1,1,m);
while(q--)
{
l=read(),r=read();
printf("%d\n",query(1,1,m,l,r).val);
}
return 0;
}

T3 sailing

第一步,我们考虑舰队可以”整体地“位于哪几个位置

把环境和舰队的图都转化成一个\(01\)序列,可以位于一个位置当且仅当在某个区间中没有两个数同为\(1\)

考虑把其中一个序列倒序处理,就可以用\(NTT\)算出上面的答案

第二步,可以位于某个位置并不代表一定可以移动的到

从一个一定满足的位置(比如说舰队的原位置)开始\(bfs\),显然所有合法的位置都是相互联通的

第三步,求可以到达的格子数

一个格子可以到达,说明将舰队的\(01\)序列放在某个合法的位置上,这个位置是\(1\)

显然也可以用\(NTT\)来解决

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
#define reg register
const int MN=705,P=998244353,g=3,invg=332748118;
int n,m;
int a[MN*MN*4],b[MN*MN*4],c[MN*MN*4],N,di,invN,pos[MN*MN*4];
char mp[MN][MN];
bool rea[MN][MN];
int fpow(int x,int m){int r=1;for(;m;m>>=1,x=1ll*x*x%P)if(m&1)r=1ll*r*x%P;return r;}
void NTT(int *a,int type)
{
reg int wi,w,i,j,p,k;
for(i=0;i<N;++i)if(i<pos[i])std::swap(a[i],a[pos[i]]);
for(i=1;i<N;i<<=1)
{
wi=fpow(type>0?g:invg,(P-1)/(i<<1));
for(j=i<<1,p=0;p<N;p+=j)
for(w=1,k=0;k<i;++k,w=1ll*w*wi%P)
{
int X=a[p+k],Y=1ll*a[i+p+k]*w%P;
a[p+k]=(X+Y)%P;a[i+p+k]=(X-Y+P)%P;
}
}
if(type<0)for(i=0;i<N;++i)a[i]=1ll*a[i]*invN%P;
}
std::queue<std::pair<int,int> > q;
const int dx[4]={0,-1,0,1},dy[4]={1,0,-1,0};
void bfs(int x,int y)
{
q.push(make_pair(x,y));rea[x][y]=false;
while(!q.empty())
{
int X=q.front().first,Y=q.front().second;q.pop();
a[(X-1)*m+Y]=1;
for(reg int i=0;i<4;++i)if(rea[X+dx[i]][Y+dy[i]])
rea[X+dx[i]][Y+dy[i]]=false,q.push(make_pair(X+dx[i],Y+dy[i]));
}
}
int main()
{
int i,j,x1=P,x2=-P,y1=P,y2=-P,ans=0;
n=read();m=read();
for(i=1;i<=n;++i) scanf("%s",mp[i]+1);
for(i=1;i<=n;++i)for(j=1;j<=m;++j)
{
if(mp[i][j]=='#') a[(i-1)*m+j]=1;
if(mp[i][j]=='o') x1=min(x1,i),x2=max(x2,i),y1=min(y1,j),y2=max(y2,j);
}
int T=(x2-x1)*m+y2-y1+1;
for(i=1;i<=n;++i)for(j=1;j<=m;++j)
if(mp[i][j]=='o') b[(i-x1)*m+j-y1+1]=c[T-(i-x1)*m-j+y1]=1;
for(N=1,di=0;N<=m*n*2;N<<=1,++di);invN=fpow(N,P-2);
for(i=0;i<N;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(di-1));
NTT(a,1);NTT(b,1);NTT(c,1);
for(i=0;i<N;++i) a[i]=1ll*a[i]*c[i]%P;
NTT(a,-1);
for(i=1;i+(x2-x1)<=n;++i)for(j=1;j+(y2-y1)<=m;++j)if(a[T+(i-1)*m+j]==0)rea[i][j]=true;
memset(a,0,sizeof a);bfs(x1,y1);NTT(a,1);
for(i=0;i<N;++i) a[i]=1ll*a[i]*b[i]%P;
NTT(a,-1);
for(i=2;i<=n*m+1;++i) if(a[i]) ++ans;
return 0*printf("%d\n",ans);
}

Blog来自PaperCloud,未经允许,请勿转载,TKS!

FCS省选模拟赛 Day1的更多相关文章

  1. FCS省选模拟赛 Day7

    Description  Solution T1 island 考虑把问题成两部分计算 纵坐标的距离和很好计算,在输入的同时一次计算了就完事 横坐标又分成两部分 分别在\(y\)轴不同侧的矩形的距离和 ...

  2. FCS省选模拟赛 Day3

    Description  Solution T1 game 咕咕咕 T2 string fail树各个节点的深度之和怎么求? 我们考虑每个前缀的深度是什么 发现这个值就相当于有多少个前缀等于它的后缀 ...

  3. FCS省选模拟赛 Day4

    传送门 Solution Code  /* 斯坦纳树:O(n*3^n+kE*2^n) 暂且把O(k*E)当成是spfa的复杂度 15:15~16:20 原题:bzoj_4774 */ #include ...

  4. FCS省选模拟赛 Day5

    传送门 Solution Code  #include<bits/stdc++.h> #define ll long long #define max(a,b) ((a)>(b)?( ...

  5. 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...

  6. 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...

  7. 队爷的新书 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的新书 题解:看到这题就想到了 poetize 的封 ...

  8. CH Round #48 - Streaming #3 (NOIP模拟赛Day1)

    A.数三角形 题目:http://www.contesthunter.org/contest/CH%20Round%20%2348%20-%20Streaming%20%233%20(NOIP模拟赛D ...

  9. CH Round #54 - Streaming #5 (NOIP模拟赛Day1)

    A.珠 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2354%20-%20Streaming%20%235%20(NOIP模拟赛Day1)/珠 题解:sb题, ...

随机推荐

  1. 返璞归真——OO第四单元总结暨学期总结

    本次作业是第四单元的最后一次作业,也是本学期面向对象的最后一次作业,在此我将分别对第四单元和整个学期进行总结. 一.本单元的两次作业 第四单元的作业是关于UML的一些处理.UML语言是一种区别于具体语 ...

  2. BUAA_OO第四单元总结性博客作业——UML(Floyd实现规则检查?)

    一.架构设计 1.UML第一次作业——类图 第一次作业基于不同element在UML规格中的从属关系来设计架构.继承了UmlInteraction接口的MyUmlInteraction类是主要的交互层 ...

  3. HTML学习摘要4

    DAY 4 text-align 属性规定了元素中文本的水平对齐方式: <html> <body> <h1 style="text-align:center&q ...

  4. 分享一个vue项目“脚手架”项目的实现步骤

    搭建缘由 源于公司每次新启动一个由多人协同开发的项目都由负责人初始化项目之后,每个人再去从私服pull一下项目才开始开发.但是每次初始化工程都是一步步的造轮子,一个个依赖去安装,新建一个个不同功能的文 ...

  5. Zabbix-报警之微信(Wechat alert)告警

    1.前言 Zabbix告警发送是监控系统的重要功能之一.Zabbix可以通过多种方式把告警信息发送到指定人,常用的有邮件,短信报警方式,但是越来越多的企业开始使用zabbix结合微信作为主要的告警方式 ...

  6. jmeter性能测试监控

    Jmeter监控服务器资源配置如下: 1.进入https://jmeter-plugins.org/downloads/all/下载plugins-manager.jar,放置到jmeter安装目录/ ...

  7. Java精通并发-死锁检测与相关工具详解

    关于死锁其实在之前https://www.cnblogs.com/webor2006/p/10659938.html的jvm学习中已经详细举过例子了,不过这里再来复习一下,另外是从并发这个专题领域的角 ...

  8. LGOJ P2048 [NOI2010]超级钢琴

    题目描述 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为Ai,其中A ...

  9. 《The One!团队》:BETA Scrum metting3

    项目 内容 作业所属课程 所属课程 作业要求 作业要求 团队名称 < The One !> 作业学习目标 (1)掌握软件黑盒测试技术:(2)学会编制软件项目总结PPT.项目验收报告:(3) ...

  10. PHP Web 木马扫描器

    直接放在网站根目录运行即可 <?php /**************PHP Web木马扫描器************************/ /* [+] 版本: v1.0 */ /* [+ ...