5215: [Lydsy2017省队十连测]商店购物
可能FFT学傻了,第一反应是前面300*300背包,后面FFT...
实际上前面背包,后面组合数即可.只是这是一道卡常题,需要注意常数..
1 //Achen 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdlib> 6 #include<vector> 7 #include<cstdio> 8 #include<queue> 9 #include<cmath> 10 #include<set> 11 #include<map> 12 #define For(i,a,b) for(int i=(a);i<=(b);i++) 13 #define Rep(i,a,b) for(int i=(a);i>=(b);i--) 14 const int N=307,up=10000000,p=1000000007; 15 typedef long long LL; 16 typedef double db; 17 using namespace std; 18 int n,m,k,w[N],prw; 19 LL fac[up+7],inv[up+7],f[N*N],sum[N],g[up+7],ans; 20 21 template<typename T> void read(T &x) { 22 char ch=getchar(); x=0; T f=1; 23 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar(); 24 if(ch=='-') f=-1,ch=getchar(); 25 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f; 26 } 27 28 LL C(int n,int m) { 29 if(n<m||n<0||m<0) return 0; 30 return fac[n]*inv[m]%p*inv[n-m]%p; 31 } 32 33 LL mo(LL x) { if(x<0) return x+p; if(x>=p) return x-p; return x; } 34 35 //#define DEBUG 36 int main() { 37 #ifdef DEBUG 38 freopen("1.in","r",stdin); 39 //freopen(".out","w",stdout); 40 #endif 41 read(n); read(m); read(k); 42 inv[0]=inv[1]=fac[0]=1; 43 For(i,2,k+n-m) inv[i]=mo(p-p/i*inv[p%i]%p); 44 For(i,1,k+n-m) fac[i]=fac[i-1]*i%p,inv[i]=inv[i-1]*inv[i]%p; 45 For(i,1,m) read(w[i]); 46 f[0]=1; 47 For(i,1,m) { 48 sum[0]=1; 49 prw+=w[i]; 50 For(j,1,prw) sum[j]=mo(sum[j-1]+f[j]); 51 Rep(j,prw,0) 52 f[j]=mo(sum[j]-(j-w[i]-1>=0?sum[j-w[i]-1]:0)); 53 } 54 g[0]=1; 55 if(!(n-m)) { 56 if(k<=prw) printf("%lld ",f[k]); 57 else puts("0"); 58 return 0; 59 } 60 For(i,0,min(prw,k)) 61 ans=mo(ans+f[i]*C(k-i+(n-m)-1,n-m-1)%p); 62 printf("%lld ",ans); 63 return 0; 64 }
5216: [Lydsy2017省队十连测]公路建设
感觉可以lct+回滚莫对乱搞
正解:发现n很小,让人浮想连篇
线段树,每个节点维护这段区间的边可选的情况下在最小生成森林上的边,n很小所以每个点上的边都不超过99条
线段树update的时候用归并排序,查的时候直接快拍一波.
求最小生产森林的时候并查集维护.
昨天写的时候对拍十分完美,看了有看也找不出毛病,一直WA.今天重构了下代码就过了...
1 //Achen 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdlib> 6 #include<vector> 7 #include<cstdio> 8 #include<queue> 9 #include<cmath> 10 #include<set> 11 #include<map> 12 const int N=200007; 13 #define For(i,a,b) for(int i=(a);i<=(b);i++) 14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--) 15 typedef long long LL; 16 typedef double db; 17 using namespace std; 18 int n,m,q; 19 20 template<typename T> void read(T &x) { 21 char ch=getchar(); x=0; T f=1; 22 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar(); 23 if(ch=='-') f=-1,ch=getchar(); 24 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f; 25 } 26 27 struct edge { int u,v,w; }e[N]; 28 vector<int>vc[N*20]; 29 30 #define lc x<<1 31 #define rc ((x<<1)|1) 32 #define mid ((l+r)>>1) 33 34 int fa[N]; 35 int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); } 36 37 int sta[N],top; 38 void update(int x) { 39 int i=0,j=0,up1=vc[lc].size(),up2=vc[rc].size(); top=0; 40 while(i<up1||j<up2) { 41 if(j>=up2||(i<up1&&j<up2&e[vc[lc][i]].w<=e[vc[rc][j]].w)) sta[++top]=vc[lc][i++]; 42 else sta[++top]=vc[rc][j++]; 43 } 44 For(i,1,top) { 45 int u=e[sta[i]].u,v=e[sta[i]].v; 46 fa[u]=u; fa[v]=v; 47 } 48 For(i,1,top) { 49 int u=e[sta[i]].u,v=e[sta[i]].v; 50 if(find(u)!=find(v)) { 51 fa[find(u)]=find(v); 52 vc[x].push_back(sta[i]); 53 } 54 } 55 } 56 57 void build(int x,int l,int r) { 58 if(l==r) { vc[x].push_back(l); return; } 59 build(lc,l,mid); build(rc,mid+1,r); 60 update(x); 61 } 62 63 void qry(int x,int l,int r,int ql,int qr) { 64 if(l>=ql&&r<=qr) { 65 int up=vc[x].size(); 66 For(i,0,up-1) sta[++top]=vc[x][i]; 67 return ; 68 } 69 if(ql<=mid) qry(lc,l,mid,ql,qr); 70 if(qr>mid) qry(rc,mid+1,r,ql,qr); 71 } 72 73 bool cmp(const int &A,const int &B) { 74 return e[A].w<e[B].w; 75 } 76 77 int solve(int l,int r) { 78 top=0; if(l>r) swap(l,r); 79 qry(1,1,m,l,r); 80 sort(sta+1,sta+top+1,cmp); 81 int rs=0,cnt=0; 82 For(i,1,n) fa[i]=i; 83 For(i,1,top) { 84 int u=e[sta[i]].u,v=e[sta[i]].v,w=e[sta[i]].w; 85 if(find(u)!=find(v)) { 86 fa[find(u)]=find(v); 87 rs+=w; cnt++; 88 if(cnt>=n-1) break; 89 } 90 } 91 return rs; 92 } 93 94 //#define DEBUG 95 int main() { 96 #ifdef DEBUG 97 freopen("1.in","r",stdin); 98 //freopen(".out","w",stdout); 99 #endif 100 read(n); read(m); read(q); 101 For(i,1,m) { 102 read(e[i].u); read(e[i].v); read(e[i].w); 103 } 104 build(1,1,m); 105 while(q--) { 106 int l,r; 107 read(l); read(r); 108 printf("%d ",solve(l,r)); 109 } 110 return 0; 111 }
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=707,M=2048576; 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[5]={0,0,1,-1},ty[5]={1,-1,0,0},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=0; T f=1; while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar(); if(ch=='-') f=-1,ch=getchar(); for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; 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+1)&&x<=n&&y>=(ry-ly+1)&&y<=m&&!vis[(x-1)*m+y-1]&&(A[(x-1)*m+y-1].x==0); } queue<node>que; void bfs(node s) { que.push(s); vis[(s.x-1)*m+s.y-1]=1; while(!que.empty()) { node tp=que.front(); que.pop(); int x=tp.x,y=tp.y,id=(tp.x-1)*m+tp.y-1; C[id-(rx-lx+1)*m+1+ly-1+m-ry]=E((A[id].x==0),0); For(i,0,3) if(ok(x+tx[i],y+ty[i])) { vis[(x+tx[i]-1)*m+y+ty[i]-1]=1; que.push(node(x+tx[i],y+ty[i])); } } } void FFT(E a[],int n,int f) { For(i,0,n-1) if(i<r[i]) swap(a[i],a[r[i]]); for(int i=1;i<n;i<<=1) { E wn(cos(pi/i),f*sin(pi/i)); for(int j=0,pp=(i<<1);j<n;j+=pp) { E w(1,0); for(int k=0;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==-1) { For(i,0,n-1) 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,1,n) scanf("%s",s[i]+1); lx=n+1,ly=m+1,rx=0,ry=0; For(i,1,n) For(j,1,m) { A[(i-1)*m+j-1]=E((s[i][j]=='#'),0); 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-1,B_len=A_len; For(i,1,n) For(j,1,m) if(s[i][j]=='o') { int x=i+(n-rx),y=j+(m-ry); B[B_len-((x-1)*m+y-1)]=E(1,0); } int len=A_len+B_len,nn,ll=0; for(nn=1;nn<=len;nn<<=1) ll++; For(i,1,nn) r[i]=(r[i>>1]>>1)|((i&1)<<ll-1); FFT(A,nn,1); FFT(B,nn,1); For(i,0,nn-1) A[i]=A[i]*B[i]; FFT(A,nn,-1); bfs(node(rx,ry)); For(i,0,nn) B[i]=E(0,0); For(i,1,n) For(j,1,m) if(s[i][j]=='o') { int x=i-lx+1,y=j-ly+1; B[(x-1)*m+y-1]=E(1,0); } FFT(B,nn,1); FFT(C,nn,1); For(i,0,nn-1) C[i]=C[i]*B[i]; FFT(C,nn,-1); int ans=0; For(i,0,n*m-1) if((int)C[i].x) ans++; printf("%d ",ans); return 0; }
5219: [Lydsy2017省队十连测]最长路径
竞赛图的性质:
1.竞赛图存在哈密顿路径
2.强联通竞赛图存在哈密顿回路
3.竞赛图缩点后形成一条链
证明:数学归纳法
1 //Achen 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdlib> 6 #include<vector> 7 #include<cstdio> 8 #include<queue> 9 #include<cmath> 10 #include<set> 11 #include<map> 12 #define For(i,a,b) for(int i=(a);i<=(b);i++) 13 #define Rep(i,a,b) for(int i=(a);i>=(b);i--) 14 const int N=2007; 15 typedef long long LL; 16 typedef double db; 17 using namespace std; 18 int n,p; 19 LL f[N],g[N],power[N*N],C[N][N],ans[N]; 20 21 template<typename T> void read(T &x) { 22 char ch=getchar(); x=0; T f=1; 23 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar(); 24 if(ch=='-') f=-1,ch=getchar(); 25 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f; 26 } 27 28 //#define DEBUG 29 int main() { 30 #ifdef DEBUG 31 freopen("1.in","r",stdin); 32 //freopen(".out","w",stdout); 33 #endif 34 read(n); read(p); 35 power[0]=1; 36 For(i,1,n*n) power[i]=power[i-1]*2%p; 37 For(i,0,n) C[i][0]=1; 38 For(i,1,n) For(j,1,i) C[i][j]=(C[i-1][j]+C[i-1][j-1])%p; 39 int up=n*(n-1)/2; 40 f[0]=1; 41 For(i,1,n) f[i]=power[i*(i-1)/2]; 42 For(i,1,n) { 43 g[i]=f[i]; 44 For(j,1,i-1) g[i]=(g[i]-C[i][j]*g[j]%p*f[i-j]%p+p)%p; 45 } 46 For(i,1,n) For(j,0,n) if(i+j<=n) { 47 ans[i+j]=(ans[i+j]+C[n-1][i-1]*g[i]%p*C[n-i][j]%p*f[j]%p*f[n-j-i])%p; 48 } 49 For(k,1,n) printf("%lld ",ans[k]); 50 return 0; 51 }