zoukankan      html  css  js  c++  java
  • 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
    ",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 }
    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
    ",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
    ",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
    ",ans[k]);    
    50     return 0;
    51 }
    View Code
  • 相关阅读:
    jvisualm 结合 visualGC 进行jvm监控,并分析垃圾回收
    linux 查看服务器cpu 与内存配置
    arthas 使用总结
    selinux contexts 安全上下文的临时更改
    Android 8.1 Doze模式分析(五) Doze白名单及Debug方式
    Window 任意窗口置顶软件Window TopMost Control
    Android ApkToolPlus一个可视化的跨平台 apk 分析工具
    SVN Please execute the 'Cleanup' command.
    Android 如何在64位安卓系统中使用32位SO库
    Android cmd命令查看apk是32位还是64位?
  • 原文地址:https://www.cnblogs.com/Achenchen/p/8979481.html
Copyright © 2011-2022 走看看