Lydsy2017省队十连测
5215: [Lydsy2017省队十连测]商店购物
可能FFT学傻了,第一反应是前面300*300背包,后面FFT...
实际上前面背包,后面组合数即可.只是这是一道卡常题,需要注意常数..
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#include<map>
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int N=,up=,p=;
typedef long long LL;
typedef double db;
using namespace std;
int n,m,k,w[N],prw;
LL fac[up+],inv[up+],f[N*N],sum[N],g[up+],ans; template<typename T> void read(T &x) {
char ch=getchar(); x=; T f=;
while(ch!='-'&&(ch<''||ch>'')) ch=getchar();
if(ch=='-') f=-,ch=getchar();
for(;ch>=''&&ch<='';ch=getchar()) x=x*+ch-''; x*=f;
} LL C(int n,int m) {
if(n<m||n<||m<) return ;
return fac[n]*inv[m]%p*inv[n-m]%p;
} LL mo(LL x) { if(x<) return x+p; if(x>=p) return x-p; return x; } //#define DEBUG
int main() {
#ifdef DEBUG
freopen("1.in","r",stdin);
//freopen(".out","w",stdout);
#endif
read(n); read(m); read(k);
inv[]=inv[]=fac[]=;
For(i,,k+n-m) inv[i]=mo(p-p/i*inv[p%i]%p);
For(i,,k+n-m) fac[i]=fac[i-]*i%p,inv[i]=inv[i-]*inv[i]%p;
For(i,,m) read(w[i]);
f[]=;
For(i,,m) {
sum[]=;
prw+=w[i];
For(j,,prw) sum[j]=mo(sum[j-]+f[j]);
Rep(j,prw,)
f[j]=mo(sum[j]-(j-w[i]->=?sum[j-w[i]-]:));
}
g[]=;
if(!(n-m)) {
if(k<=prw) printf("%lld\n",f[k]);
else puts("");
return ;
}
For(i,,min(prw,k))
ans=mo(ans+f[i]*C(k-i+(n-m)-,n-m-)%p);
printf("%lld\n",ans);
return ;
}
5216: [Lydsy2017省队十连测]公路建设
感觉可以lct+回滚莫对乱搞
正解:发现n很小,让人浮想连篇
线段树,每个节点维护这段区间的边可选的情况下在最小生成森林上的边,n很小所以每个点上的边都不超过99条
线段树update的时候用归并排序,查的时候直接快拍一波.
求最小生产森林的时候并查集维护.
昨天写的时候对拍十分完美,看了有看也找不出毛病,一直WA.今天重构了下代码就过了...
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#include<map>
const int N=;
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
typedef long long LL;
typedef double db;
using namespace std;
int n,m,q; template<typename T> void read(T &x) {
char ch=getchar(); x=; T f=;
while(ch!='-'&&(ch<''||ch>'')) ch=getchar();
if(ch=='-') f=-,ch=getchar();
for(;ch>=''&&ch<='';ch=getchar()) x=x*+ch-''; x*=f;
} struct edge { int u,v,w; }e[N];
vector<int>vc[N*]; #define lc x<<1
#define rc ((x<<1)|1)
#define mid ((l+r)>>1) int fa[N];
int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); } int sta[N],top;
void update(int x) {
int i=,j=,up1=vc[lc].size(),up2=vc[rc].size(); top=;
while(i<up1||j<up2) {
if(j>=up2||(i<up1&&j<up2&e[vc[lc][i]].w<=e[vc[rc][j]].w)) sta[++top]=vc[lc][i++];
else sta[++top]=vc[rc][j++];
}
For(i,,top) {
int u=e[sta[i]].u,v=e[sta[i]].v;
fa[u]=u; fa[v]=v;
}
For(i,,top) {
int u=e[sta[i]].u,v=e[sta[i]].v;
if(find(u)!=find(v)) {
fa[find(u)]=find(v);
vc[x].push_back(sta[i]);
}
}
} void build(int x,int l,int r) {
if(l==r) { vc[x].push_back(l); return; }
build(lc,l,mid); build(rc,mid+,r);
update(x);
} void qry(int x,int l,int r,int ql,int qr) {
if(l>=ql&&r<=qr) {
int up=vc[x].size();
For(i,,up-) sta[++top]=vc[x][i];
return ;
}
if(ql<=mid) qry(lc,l,mid,ql,qr);
if(qr>mid) qry(rc,mid+,r,ql,qr);
} bool cmp(const int &A,const int &B) {
return e[A].w<e[B].w;
} int solve(int l,int r) {
top=; if(l>r) swap(l,r);
qry(,,m,l,r);
sort(sta+,sta+top+,cmp);
int rs=,cnt=;
For(i,,n) fa[i]=i;
For(i,,top) {
int u=e[sta[i]].u,v=e[sta[i]].v,w=e[sta[i]].w;
if(find(u)!=find(v)) {
fa[find(u)]=find(v);
rs+=w; cnt++;
if(cnt>=n-) break;
}
}
return rs;
} //#define DEBUG
int main() {
#ifdef DEBUG
freopen("1.in","r",stdin);
//freopen(".out","w",stdout);
#endif
read(n); read(m); read(q);
For(i,,m) {
read(e[i].u); read(e[i].v); read(e[i].w);
}
build(,,m);
while(q--) {
int l,r;
read(l); read(r);
printf("%d\n",solve(l,r));
}
return ;
}
5217: [Lydsy2017省队十连测]航海舰队
忘了FFT的用处了...
A把图拉成一维,有障碍的格子设为1
B把舰队的一整块矩形移到图的右下角,拉成一维,有舰的地方设为1
把A和倒置的B FFT求出图中以哪些格子为右下角的整块矩形可以放下这个舰队
$A[pos]= \sum B'[i]*A[pos-i]$
$A[pos]==0$:pos为右下角的矩形,不存在又是舰又是障碍的格子
根据可不可以放下从右下角的起点开始bfs,找到可以走到的那些右下角
这些点就是实际可以作为右下角的点.
脑子有点木,为了便于理解一开始算的右下角,bfs的时候标记出可以放的是又转到对应左上角去了
然后bfs后得到的标记数组和不倒置的舰队数组FFT求出那些点可以到达.$C[pos]= \sum B[i]*C[pos-i]$
当前的$pos$是舰队中第$i$个,$pos-i$的位置能不能作为左上角.若存在第i个是舰且$pos-i$的位置能作为左上角,即$C[pos]>0$,$pos$可以被到达
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#include<map>
#define pi acos(-1)
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int N=,M=;
typedef long long LL;
typedef double db;
using namespace std;
char s[N][N];
int lx,ly,rx,ry,n,m,pos,r[M],tx[]={,,,-},ty[]={,-,,},vis[M]; struct E {
double x,y;
E(){}
E(db x,db y):x(x),y(y){}
friend E operator +(const E&A,const E&B) { return E(A.x+B.x,A.y+B.y); }
friend E operator -(const E&A,const E&B) { return E(A.x-B.x,A.y-B.y); }
friend E operator *(const E&A,const E&B) { return E(A.x*B.x-A.y*B.y,A.x*B.y+A.y*B.x); }
friend E operator /(const E&A,const db&B) { return E(A.x/B,A.y/B); }
/*E operator + (const E &d) const { return E(x+d.x,y+d.y); }
E operator - (const E &d) const { return E(x-d.x,y-d.y); }
E operator * (const E &d) const { return E(x*d.x-y*d.y,x*d.y+y*d.x); }
E operator / (const double &d) const { return E(x/d,y/d); }*/
};
E A[M],B[M],C[M]; template<typename T> void read(T &x) {
char ch=getchar(); x=; T f=;
while(ch!='-'&&(ch<''||ch>'')) ch=getchar();
if(ch=='-') f=-,ch=getchar();
for(;ch>=''&&ch<='';ch=getchar()) x=x*+ch-''; x*=f;
} struct node {
int x,y;
node(int x,int y):x(x),y(y){}
}; int ok(int x,int y) {
return x>=(rx-lx+)&&x<=n&&y>=(ry-ly+)&&y<=m&&!vis[(x-)*m+y-]&&(A[(x-)*m+y-].x==);
} queue<node>que;
void bfs(node s) {
que.push(s);
vis[(s.x-)*m+s.y-]=;
while(!que.empty()) {
node tp=que.front();
que.pop();
int x=tp.x,y=tp.y,id=(tp.x-)*m+tp.y-;
C[id-(rx-lx+)*m++ly-+m-ry]=E((A[id].x==),);
For(i,,) if(ok(x+tx[i],y+ty[i])) {
vis[(x+tx[i]-)*m+y+ty[i]-]=;
que.push(node(x+tx[i],y+ty[i]));
}
}
} void FFT(E a[],int n,int f) {
For(i,,n-) if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=;i<n;i<<=) {
E wn(cos(pi/i),f*sin(pi/i));
for(int j=,pp=(i<<);j<n;j+=pp) {
E w(,);
for(int k=;k<i;k++,w=w*wn) {
E x=a[j+k],y=a[j+k+i]*w;
a[j+k]=x+y; a[j+k+i]=x-y;
}
}
}
if(f==-) {
For(i,,n-) a[i].x=(int)(a[i].x/n+0.5);
}
} //#define DEBUG
int main() {
#ifdef DEBUG
freopen("std.in","r",stdin);
//freopen(".out","w",stdout);
#endif
read(n); read(m);
For(i,,n) scanf("%s",s[i]+);
lx=n+,ly=m+,rx=,ry=;
For(i,,n) For(j,,m) {
A[(i-)*m+j-]=E((s[i][j]=='#'),);
if(s[i][j]=='o') lx=min(lx,i),ly=min(ly,j),rx=max(rx,i),ry=max(ry,j);
}
int A_len=n*m-,B_len=A_len;
For(i,,n) For(j,,m) if(s[i][j]=='o') {
int x=i+(n-rx),y=j+(m-ry);
B[B_len-((x-)*m+y-)]=E(,);
}
int len=A_len+B_len,nn,ll=;
for(nn=;nn<=len;nn<<=) ll++;
For(i,,nn) r[i]=(r[i>>]>>)|((i&)<<ll-);
FFT(A,nn,); FFT(B,nn,);
For(i,,nn-) A[i]=A[i]*B[i];
FFT(A,nn,-);
bfs(node(rx,ry));
For(i,,nn) B[i]=E(,);
For(i,,n) For(j,,m) if(s[i][j]=='o') {
int x=i-lx+,y=j-ly+;
B[(x-)*m+y-]=E(,);
}
FFT(B,nn,);
FFT(C,nn,);
For(i,,nn-) C[i]=C[i]*B[i];
FFT(C,nn,-);
int ans=;
For(i,,n*m-) if((int)C[i].x) ans++;
printf("%d\n",ans);
return ;
}
5219: [Lydsy2017省队十连测]最长路径
竞赛图的性质:
1.竞赛图存在哈密顿路径
2.强联通竞赛图存在哈密顿回路
3.竞赛图缩点后形成一条链
证明:数学归纳法
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#include<map>
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int N=;
typedef long long LL;
typedef double db;
using namespace std;
int n,p;
LL f[N],g[N],power[N*N],C[N][N],ans[N]; template<typename T> void read(T &x) {
char ch=getchar(); x=; T f=;
while(ch!='-'&&(ch<''||ch>'')) ch=getchar();
if(ch=='-') f=-,ch=getchar();
for(;ch>=''&&ch<='';ch=getchar()) x=x*+ch-''; x*=f;
} //#define DEBUG
int main() {
#ifdef DEBUG
freopen("1.in","r",stdin);
//freopen(".out","w",stdout);
#endif
read(n); read(p);
power[]=;
For(i,,n*n) power[i]=power[i-]*%p;
For(i,,n) C[i][]=;
For(i,,n) For(j,,i) C[i][j]=(C[i-][j]+C[i-][j-])%p;
int up=n*(n-)/;
f[]=;
For(i,,n) f[i]=power[i*(i-)/];
For(i,,n) {
g[i]=f[i];
For(j,,i-) g[i]=(g[i]-C[i][j]*g[j]%p*f[i-j]%p+p)%p;
}
For(i,,n) For(j,,n) if(i+j<=n) {
ans[i+j]=(ans[i+j]+C[n-][i-]*g[i]%p*C[n-i][j]%p*f[j]%p*f[n-j-i])%p;
}
For(k,,n) printf("%lld\n",ans[k]);
return ;
}
Lydsy2017省队十连测的更多相关文章
- bzoj 5216 [Lydsy2017省队十连测]公路建设 线段树维护 最小生成树
[Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 93 Solved: 53[Submit][Status][ ...
- bzoj 5216: [Lydsy2017省队十连测]公路建设
5216: [Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 66 Solved: 37[Submit][St ...
- 2018.09.26 bzoj5218: [Lydsy2017省队十连测]友好城市(回滚莫队)
传送门 比较简单的一道回滚莫队吧. 每次询问用bitset优化kosaraju统计答案. 就是有点难调. 然后向dzyo学长学习了回滚莫队的一种简洁的实现方式,就是直接建立一个sqrt(m)∗sqrt ...
- bzoj 5218: [Lydsy2017省队十连测]友好城市
题意: 这题显然直接tarjan是做不了的. 这里安利另一个求SCC的算法Kosaraju,学习的话可以见这篇博客 于是结合莫队,我们有了个暴力. 发现主要瓶颈是dfs过程中找最小的未经过的点,我们用 ...
- 【BZOJ 5222】[Lydsy2017省队十连测]怪题
题目大意: 传送门 给一个长度为$n(n<=200)$的数列$h$,再给$m$个可以无限使用的操作,第$i$个操作为给长度为花费$c_i$的价值给长度为$l_i$的数列子序列+1或-1,求将数列 ...
- 2018.09.26 bzoj5221: [Lydsy2017省队十连测]偏题(数学推导+矩阵快速幂)
传送门 由于没有考虑n<=1的情况T了很久啊. 这题很有意思啊. 考试的时候根本不会,骗了30分走人. 实际上变一个形就可以了. 推导过程有点繁杂. 直接粘题解上的请谅解. 不得不说这个推导很妙 ...
- BZOJ5217: [Lydsy2017省队十连测]航海舰队 FFT
被FFT的空间卡了半天 后来发现根本不用开那么大... 首先可以把包含舰艇的那个小矩形找出来 将它一行一行连接成一个串T 其中舰艇位置为1其他位置为0 将大矩形也连成串S 其中礁石为1其他为0 两个串 ...
- BZOJ5217:[Lydsy2017省队十连测]航海舰队——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5217 Byteasar 组建了一支舰队!他们现在正在海洋上航行着.海洋可以抽象成一张n×m 的网格 ...
- bzoj 5217: [Lydsy2017省队十连测]航海舰队
Description Byteasar 组建了一支舰队!他们现在正在海洋上航行着.海洋可以抽象成一张n×m 的网格图,其中有些位置是" .",表示这一格是海水,可以通过:有些位置 ...
随机推荐
- Restoring Road Network Floyd
问题 C: Restoring Road Network 时间限制: 1 Sec 内存限制: 128 MB提交: 731 解决: 149[提交] [状态] [讨论版] [命题人:admin] 题目 ...
- 2018今日头条湖北省赛【D】
[题目链接]https://www.nowcoder.com/acm/contest/104/C 不知道这题为啥没过.队友现场推的都是对的..233333好像代码写的有问题,下来就很恼火. 题意大概就 ...
- 001-Java命名规范
1. 包名 多个单词都小写xxxyyyzzz 2.类名和接口名 多单词组成时,所有单词的首字母大写XxxYyyZzz 3.变量名和方法名 多单词组成时,第一个单词首字母小写,后面单词首字母军大写 xx ...
- 【第三周读书笔记】浅谈node.js中的异步回调和用js-xlsx操作Excel表格
在初步学习了node.js之后,我发现他的时序问题我一直都很模糊不清,所以我专门学习了一下这一块. 首先我们来形象地理解一下进程和线程: 进程:CPU执行任务的模块.线程:模块中的最小单元. 例如:c ...
- Git的配置及克隆项目到本地
- ionic 滚动条 ion-scroll 用于创建一个可滚动的容器
ionic 滚动条 ion-scroll ion-scroll 用于创建一个可滚动的容器. 用法 <ion-scroll [delegate-handle=""] [dire ...
- 字典配合split分裂填充
Sub 配送日报()lastrow = Sheets("运营日报").Range("a1048576").End(xlUp).Rowarr = Sheets(& ...
- 获取的Json数据需要去掉特殊符号
我们平时在后台代码里面获取的Json数据如下情况: json会包含\r ,\n, \ 等一些特殊的符号.下面我们就写一个方法去消除这些特殊符号,在代码里获取到纯净的json. public stat ...
- python中的OrderedDict
该类型存放顺序和添加顺序一致,比如逐个赋值,但和dict直接转化过去的顺序不一定一样. d1 = collections.OrderedDict() d1['b'] = 'B'd1['a'] = 'A ...
- BigDecimal踩过的大坑
通常Java中涉及金钱相关的计算为了保持精度,会采用BigDecimal来实现,但是BigDecimal中创建BigDecimal类对象的时候,如果使用直接new的话,必须是String类型的参数,否 ...