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省队十连测的更多相关文章

  1. bzoj 5216 [Lydsy2017省队十连测]公路建设 线段树维护 最小生成树

    [Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 93  Solved: 53[Submit][Status][ ...

  2. bzoj 5216: [Lydsy2017省队十连测]公路建设

    5216: [Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 66  Solved: 37[Submit][St ...

  3. 2018.09.26 bzoj5218: [Lydsy2017省队十连测]友好城市(回滚莫队)

    传送门 比较简单的一道回滚莫队吧. 每次询问用bitset优化kosaraju统计答案. 就是有点难调. 然后向dzyo学长学习了回滚莫队的一种简洁的实现方式,就是直接建立一个sqrt(m)∗sqrt ...

  4. bzoj 5218: [Lydsy2017省队十连测]友好城市

    题意: 这题显然直接tarjan是做不了的. 这里安利另一个求SCC的算法Kosaraju,学习的话可以见这篇博客 于是结合莫队,我们有了个暴力. 发现主要瓶颈是dfs过程中找最小的未经过的点,我们用 ...

  5. 【BZOJ 5222】[Lydsy2017省队十连测]怪题

    题目大意: 传送门 给一个长度为$n(n<=200)$的数列$h$,再给$m$个可以无限使用的操作,第$i$个操作为给长度为花费$c_i$的价值给长度为$l_i$的数列子序列+1或-1,求将数列 ...

  6. 2018.09.26 bzoj5221: [Lydsy2017省队十连测]偏题(数学推导+矩阵快速幂)

    传送门 由于没有考虑n<=1的情况T了很久啊. 这题很有意思啊. 考试的时候根本不会,骗了30分走人. 实际上变一个形就可以了. 推导过程有点繁杂. 直接粘题解上的请谅解. 不得不说这个推导很妙 ...

  7. BZOJ5217: [Lydsy2017省队十连测]航海舰队 FFT

    被FFT的空间卡了半天 后来发现根本不用开那么大... 首先可以把包含舰艇的那个小矩形找出来 将它一行一行连接成一个串T 其中舰艇位置为1其他位置为0 将大矩形也连成串S 其中礁石为1其他为0 两个串 ...

  8. BZOJ5217:[Lydsy2017省队十连测]航海舰队——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5217 Byteasar 组建了一支舰队!他们现在正在海洋上航行着.海洋可以抽象成一张n×m 的网格 ...

  9. bzoj 5217: [Lydsy2017省队十连测]航海舰队

    Description Byteasar 组建了一支舰队!他们现在正在海洋上航行着.海洋可以抽象成一张n×m 的网格图,其中有些位置是" .",表示这一格是海水,可以通过:有些位置 ...

随机推荐

  1. Ant属性文件

    直接在构建文件中设置属性是好的,如果你使用的是少数属性.然而,对于一个大型项目,是要存储在一个单独的属性文件中. 存储在一个单独的文件中的属性可以让你重复使用相同的编译文件,针对不同的执行环境不同的属 ...

  2. Zookeeper怎么实现分布式锁?

    对访问资源 R1 的过程加锁,在操作 O1 结束对资源 R1 访问前,其他操作不允许访问资源 R1.以上算是对独占锁的简单定义了,那么这段定义在 Zookeeper 的"类 Unix/Lin ...

  3. [每日一个小技巧] CentOS 下使用yum安装一类软件包

    版权声明:本文为博主原创文章,欢迎转载,转载请注明出处. https://blog.csdn.net/robertsong2004/article/details/37775313 yum 提供了丰富 ...

  4. callable接口的多线程实现方式

    package com.cxy.juc; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionExce ...

  5. 一个很SB的方法,来开始调一个刚启动就SB的程序

    自己鼓捣的方法,累死我了... 遇到一个程序,这程序启动之后,会自动重新启动我的电脑, 我想调试它一下,但是遇到了问题, 如果我用调试器附加上去的话,电脑是不重起了,但是它启动了之后会立刻黑屏,全黑, ...

  6. The linux command之高级键盘技巧

    一.光标移动 二.修改文本 三.剪切和粘贴文本 四.使用历史命令

  7. Android开发 解决Installation failed due to XXX 问题

    报错信息 Android studio 安装app的时候以下报错 Installation did not succeed. The application could not be installe ...

  8. vue better-scroll 下拉上拉,加载刷新

    _initScroll(){             this.$nextTick(() => {                 if (!this.scroll) {             ...

  9. hdu6089 Rikka with Terrorist

    题意:n*m的平面内有K个不安全点,Q个询问位置在(x,y)的人能走到多少个点?走到:(x,y)和(x',y')之间的矩形中不包含不安全点. 标程: #include<bits/stdc++.h ...

  10. vsftp 被动模式配置

    直接复制粘切过来就能用 这里只讲下配置,安装方法可以直接yum 配置文件修改 anonymous_enable=NO #关闭匿名用户 xferlog_file=/var/log/vsftpd.log ...