Lydsy2017省队十连测

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\n",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\n",ans);
63     return 0;
64 }
View Code

 

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\n",solve(l,r));
109     }
110     return 0;
111 }
View Code

 

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\n",ans);
    return 0;
}
View Code

 

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\n",ans[k]);    
50     return 0;
51 }
View Code

 

posted @ 2018-05-02 11:43  啊宸  阅读(286)  评论(0编辑  收藏  举报