20191013

前言

  • 感觉自己稍迷信,但好像loj运势是吉的时候我从来没考好过……
  • 然后一天挂两场,比别人少了300分,目测20名+稳了kuku。
  • lsc又挂假对拍企图炸我心态,lsc rp--

T1

  • 考试打了个$\Theta(N^3)$DP结果还假了,15分滚粗。
  • 依靠Yu-shi大神打表找出的规律,我算是水过的这个题吧。
  • 时间复杂度$\Theta(N)$,空间复杂度$\Theta(1)$。
  • 有时间再考虑证明,先咕着吧。
#include<cstdio>
using namespace std;
int const N=2002,mod=1e9+7;
int n,m;
int tp,ans;
long long f,iv,ivv;
inline long long power(long long x,int y){
    long long as=1;
    for(;y;y>>=1,x=x*x%mod)
        if(y&1)as=as*x%mod;
    return as;
}
inline void read(){
    register char bb=getchar();
    while(bb^'('&&bb^')')bb=getchar();
    for(register int i=1;i<=m;++i,bb=getchar()){
        if(bb=='(')++tp;
        else if(tp)--tp,++ans;
    }
    return ;
}
inline int down(int x){
    return x<mod?x:x-mod;
}
int main(){
    scanf("%d%d",&n,&m);
    if(n&1)return puts("0"),0;
    if(n==m)return puts("1"),0;
    read();
    int x=n-m+1,y=(n>>1)-m+ans,z=x-y;
    if(y<z)m=y,y=z,z=m;
    if(x<y)return puts("0"),0;
    f=1;
    for(register int i=1;i<=y;++i)f=f*i%mod;
    iv=power(f,mod-2);
    for(register int i=y+1;i<=z;++i)f=f*i%mod;
    ivv=power(f,mod-2);
    for(register int i=z+1;i<=x;++i)f=f*i%mod;
    printf("%lld",f*iv%mod*ivv%mod);
    return 0;
}
View Code

T2

  • 概率dp。
  • 难点在dp含义上。
  • f[i][j][k][0/1]表示进行了i次操作,后8位是j,第9位是0/1,从第9位开始连续k位相同的方案数。
  • 取后8位可以保证最高位不会有2次进位。
  • 转移和答案统计就很简单了。
  • 显然f的第一维可以滚动。
  • 还有0取反是-1,1和0的互转用!运算。(调了1个小时……)
  • 时间复杂度$\Theta(2^8N^2)$,空间复杂度$\Theta(2^8N)$。
#include<cstdio>
using namespace std;
int const lt=1<<8;
double f[2][lt][222][2],ans;
int bs[lt],c,n,p;
inline int max(int x,int y){
    return x>y?x:y;
}
int main(){
    //freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
    scanf("%d%d%d",&c,&n,&p);
    int sec=c&(lt-1);
    c>>=8;
    int thr=0,fur=c&1,lit;
    while(c){
        if((c&1)^fur)break;
        c>>=1,++thr;
    }
    lit=n+(thr=max(thr,1));
    f[0][sec][thr][fur]=1;
    double ff=(double)p/100.0,gg=1.0-ff;
    register int now=1,cur=0;
    for(register int i=1;i<=n;++i,now=cur,cur^=1){
        for(register int j=0;j<lt;++j)
            for(register int k=1;k<=lit;++k)
                f[now][j][k][0]=f[now][j][k][1]=0;
        for(register int j=0;j<lt;++j)
            for(register int k=1;k<=lit;++k)
                for(register int u=0;u^2;++u)
                    if(f[cur][j][k][u])
                    (((((j<<1)&lt)>>8)==u)?f[now][(j<<1)&(lt-1)][k+1][u]:f[now][(j<<1)&(lt-1)][1][!u])+=ff*f[cur][j][k][u],
                    (j+1==lt?f[now][0][u?k:1][!u]:f[now][j+1][k][u])+=gg*f[cur][j][k][u];
    }
    for(register int i=0;i<8;++i)bs[1<<i]=i;
    for(register int i=1;i<lt;++i)
        for(register int j=1;j<=lit;++j)
            ans+=(f[cur][i][j][0]+f[cur][i][j][1])*bs[i&-i];
    for(register int i=1;i<=lit;++i)ans+=f[cur][0][i][0]*(i+8)+f[cur][0][i][1]*8;
    printf("%.10lf",ans);
    return 0;
}
View Code

T3

  • 理解了题意其实不难。
  • 如果有奇环那么直接输出-1,可以黑白染色进行判断。
  • 否则找出连通图中最短路径最长的点对,将其他点合并。这种构造显然最优。
  • 注意图不保证连通,需要把各各连通图的答案累加。
  • 本题是稠密图,用vector实现邻接表不不用vector快20倍左右。
  • 时空复杂度$\Theta(N)$
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
int const N=1003,M=2e5+5;
int n,m,ans;
int t,qs[N],vis[N];
int q[N],dis[N];
bool vs[N];
vector<int>a[N];
inline int read(){
    int ss(0);char bb(getchar());
    while(bb<48||bb>57)bb=getchar();
    while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar();
    return ss;
}
inline int max(int x,int y){
    return x>y?x:y;
}
bool dfs(int x,int col){
    vis[x]=col,qs[++t]=x;
    for(auto &i:a[x])
        if((!vis[i]&&dfs(i,col^1))||vis[i]==col)return 1;
    return 0;
}
inline int bfs(int x){
    register int u(0),v(1),fr,dnow;
    memset(vs,1,n+1);
    vs[q[1]=x]=dis[x]=0;
    while(u^v){
        dnow=dis[fr=q[++u]]+1;
        for(register auto &i:a[fr])
            if(vs[i])vs[i]=0,dis[q[++v]=i]=dnow;
    }
    return dis[q[v]];
}
int main(){
    n=read(),m=read();
    while(m--){
        int x=read(),y=read();
        a[x].push_back(y),a[y].push_back(x);
    }
    for(register int i=1;i<=n;++i)
        if(!vis[i]){
            t=0;
            if(dfs(i,2))return puts("-1"),0;
            int now=0;
            for(register int i=1;i<=t;++i)
                now=max(now,bfs(qs[i]));
            ans+=now;
        }
    printf("%d",ans);
    return 0;
}
View Code
posted @ 2019-10-14 12:19  remarkable  阅读(138)  评论(0编辑  收藏  举报