zoukankan      html  css  js  c++  java
  • 0616考试

    T1

    Problem 1. spread
    Input file:spread.in
    Output file:spread.out
    Time limit:1 second
    Memory limit:256 MB
    Darrell 所在的国家有 N 个城市,共有 N 1 条输水管道连接它们,使得任意两个城市都可以通过这些
    输水管道连接起来。
    有一种破坏力极强的病毒被发现带入了境内,但不知道在哪个城市,现在已知如果病毒在 u 号城市爆发,
    则其会随着输水管道向向周围的城市不断扩散,但因为一些原因,扩散的速度有可能不一致。
    问题是,如果 u 号城市爆发病毒,则一段时间后可能的扩散情况有多少种?你需要对每个城市回答该问
    题。(答案可能很大,你只需要输出取模 10
    9
    + 7 的结果即可)。
    Input
    第 1 行,有 1 个整数 N,表示城市数目。
    接下来 N 1 行,每行 2 个整数:u v,表示城市 u 和 v 之间有输水管道。
    Output
    输出 1 行,包含 N 个整数,第 i 个整数表示 i 号城市爆发病毒对应的答案。
    Sample
    spread.inspread.out
    4
    1 2
    2 3
    2 4
    5 8 5 5
    Note
    样例中,如果 1 号城市爆发病毒,则可能的扩散情况有:[1],[1;2],[1;2;3],[1;2;4],[1;2;3;4],共 5 种。
    如果 2 号城市爆发病毒,则可能的扩散情况有:[2],[2;1],[2;3],[2;4],[2;1;3],[2;3;4],[2;1;4],[2;1;3;4],共 8
    种。

    DP+换根

    //By SiriusRen
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N=200500,mod=1000000007;
    int n,a[N],first[N],next[N],v[N],tot,xx,yy,f[N],g[N];
    void add(int x,int y){v[tot]=y,next[tot]=first[x],first[x]=tot++;}
    void dfs(int x,int fa){
        f[x]=1;int r=1;
        for(int i=first[x];~i;i=next[i])if(v[i]!=fa){
            dfs(v[i],x);r=(1ll*r*f[v[i]])%mod;
        }f[x]=(f[x]+r)%mod;
    }
    int pow(int x,int y){
        int r=1;
        while(y){
            if(y&1)r=1ll*r*x%mod;
            x=1ll*x*x%mod,y>>=1;
        }return r;
    }
    void dfs2(int x,int fa){
        for(int i=first[x];~i;i=next[i])if(v[i]!=fa){
            g[v[i]]=((1ll*(g[x]-1+mod)%mod*pow(f[v[i]],mod-2)%mod+1)%mod*((f[v[i]]-1+mod)%mod)+1)%mod;
            dfs2(v[i],x);
        }
    }
    int main(){
        freopen("spread.in","r",stdin);
        freopen("spread.out","w",stdout);
        memset(first,-1,sizeof(first));
        scanf("%d",&n);
        for(int i=2;i<=n;i++)scanf("%d%d",&xx,&yy),add(xx,yy),add(yy,xx);
        dfs(1,0);g[1]=f[1];dfs2(1,0);
        for(int i=1;i<=n;i++)printf("%d ",(g[i]-1+mod)%mod);
    }

    T2


    Problem 2. sing
    Input file:sing.in
    Output file:sing.out
    Time limit:1 second
    Memory limit:256 MB
    Darrell 在学唱歌。
    Darrell 已经学会了一些发音技巧,比如刚唱完 u 号音符就可以接着唱 v 号音符。
    因为一些特殊的原因,如果 Darrell 能够连续唱出 u1;u2;u3;:::;un,且 u1= u2,那么保证 u1到 un之间
    至多有 5 种不同的音符。
    Darrell 想自己编一首自己唱的歌,为了独特,他希望歌中不出现重复的音符,并且想让歌声中包含的音
    符尽量多,所以,请你告诉他最多能唱多少个音符。
    Input
    第 1 行,包含 2 个整数:N M,分别表示 Darrell 会唱的音符数及已经掌握了的发音技巧数。
    接下来 M 行,每行 2 个整数:u v,表示 Darrell 在唱完 u 后能够接着唱 v。
    Output
    输出 1 个整数,表示答案。
    Sample
    sing.insing.out
    4 5
    1 2
    2 3
    3 4
    3 1
    2 4
    4
    样例解释:可以连续唱出:3;1;2;4 的音符,所以最多为 4 个音符。
    sing.insing.out
    7 7
    1 2
    2 3
    3 4
    4 5
    5 2
    4 6
    5 7
    6
    样例解释:可以连续唱出 1;2;3;4;5;7 的音符,并且无法不重复地唱出更多的音符,所有所以最多为 6
    个音符

    Tarjan+Topsort+next_permutation

    //By SiriusRen
    #include <bits/stdc++.h>
    using namespace std;
    const int N=1000050;
    vector<int>vec[N];queue<int>q;
    int n,m,xx,yy,first[N],next[N],v[N],tot,cnt,T,mp[5][5],f[5],d[N][5],ans;
    int low[N],dfn[N],vis[N],stk[N],p[N],id[N],bl[N][5],sz[N],top,du[N],tmp[N],dis[N];
    void add(int x,int y){v[tot]=y,next[tot]=first[x],first[x]=tot++;}
    void tarjan(int x){
        dfn[x]=low[x]=++cnt,stk[++top]=x,vis[x]=1;
        for(int i=first[x];~i;i=next[i])
            if(!dfn[v[i]])tarjan(v[i]),low[x]=min(low[x],low[v[i]]);
            else if(vis[v[i]])low[x]=min(low[x],dfn[v[i]]);
        if(low[x]==dfn[x]){T++;do vis[xx=stk[top--]]=0,bl[T][sz[T]]=xx,p[xx]=T,id[xx]=sz[T]++;while(xx!=x);}
    }
    int main(){
        freopen("sing.in","r",stdin);
        freopen("sing.out","w",stdout);
        memset(first,-1,sizeof(first));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)scanf("%d%d",&xx,&yy),add(xx,yy);
        for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
        for(int i=1;i<=T;i++){
            memset(mp,0,sizeof(mp));
            for(int j=0;j<sz[i];j++)
                for(int k=first[bl[i][j]];~k;k=next[k])
                    if(p[v[k]]==i)mp[j][id[v[k]]]=1;
            for(int j=0;j<sz[i];j++)f[j]=j;
            do{
                for(int j=0;j<sz[i];j++){
                    d[bl[i][f[0]]][f[j]]=max(d[bl[i][f[0]]][f[j]],j);
                    if(!mp[f[j]][f[j+1]])break;
                }
            }while(next_permutation(f,f+sz[i]));
        }
        for(int i=1;i<=n;i++)for(int j=first[i];~j;j=next[j])if(p[v[j]]!=p[i])du[p[v[j]]]++;
        for(int i=1;i<=T;i++)if(!du[i])q.push(i);
        while(!q.empty()){
            int t=q.front();q.pop();
            for(int i=0;i<sz[t];i++)for(int j=0;j<sz[t];j++)if(i!=j)
                tmp[bl[t][j]]=max(tmp[bl[t][j]],dis[bl[t][i]]+d[bl[t][i]][j]);
            for(int i=0;i<sz[t];i++)dis[bl[t][i]]=max(dis[bl[t][i]],tmp[bl[t][i]]);
            for(int i=0;i<sz[t];i++)
                for(int j=first[bl[t][i]];~j;j=next[j])if(p[v[j]]!=t){
                    dis[v[j]]=max(dis[v[j]],dis[bl[t][i]]+1),du[p[v[j]]]--;
                    if(!du[p[v[j]]])q.push(p[v[j]]);
                }
        }
        for(int i=1;i<=n;i++)ans=max(ans,dis[i]);
        printf("%d
    ",ans+1);
    }

    T3


    Memory limit:256 MB
    Darrell 在思考一道计算题。
    给你一个尺寸为 1 N 的长条,你可以在上面切很多刀,要求竖直地切并且且完后每块的长度都是整数。
    在这种限制下其实只有 N 1 个位置可以切。
    对于一种切的方案,假如切完后每块的宽度分别是:w1;w2;w3;:::;w
    k


    wi= N),那么该种方案对应
    的完美值为:
    k∏
    i=1
    w
    2
    i
    那么问题来了,给出 M 个位置不能切(如果用 x 表示一个位置,那么切完该位置后长条变为 1 x 和
    1 (N x) 两块),
    那么所有合法切法对应的完美值的和是多少呢?(只需要输出模 10
    9
    + 7 的结果)
    Input
    第 1 行,有 2 个整数:N M,表示长条的总长度及不能切的位置数
    第 2 行,有 M 个整数:x1;x2;x3;:::;xM表示不能切的位置。
    Output
    输出 1 行,包含 1 个整数,表示满足要求的所有切法对应的完美值和。(对 10
    9
    + 7 取模后的结果)
    Sample
    count.incount.out
    3 1
    2
    13
    样例解释:一共有两种切法(用切完后的块的宽度表示):1;2 和 3,则对应答案为:1 2
    2
    + 3
    2
    = 13
    count.incount.out
    5 2
    2 3
    66
    样例解释:一共有四种切法:1;3;1、1;4、4;1 和 5,则对应答案为:1 3
    2
    1+1 4
    2
    +4
    2
    1+5
    2
    = 66
    count.incount.out
    10 9
    1 2 3 4 5 6 7 8 9
    100
    因为所有能切的位置都不能切,所以只有一种切法(就是不切):10,对应答案为:10
    2

    构造一发矩阵+矩阵快速幂

    //By SiriusRen
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define int long long
    const int mod=1000000007,N=100050;
    int n,m,xx,a[N];
    struct Matrix{int a[3][3];void init(){memset(a,0,sizeof(a));}
    void Ch(){a[0][0]=a[1][0]=a[1][2]=2,a[0][1]=a[0][2]=a[1][1]=a[2][0]=a[2][2]=1;}
    void Ch2(){a[0][0]=a[0][1]=a[0][2]=a[1][1]=a[2][2]=1,a[1][2]=2;}
    }cng,cng2,jy;
    Matrix operator*(Matrix a,Matrix b){
        Matrix c;c.init();
        for(int k=0;k<3;k++)
            for(int i=0;i<3;i++)
                for(int j=0;j<3;j++)
                    (c.a[i][j]+=a.a[i][k]*b.a[k][j])%=mod;
        return c;
    }
    Matrix operator^(Matrix a,int b){
        Matrix r;r.init();r.a[0][0]=r.a[1][1]=r.a[2][2]=1;
        while(b){
            if(b&1)r=r*a;
            a=a*a,b>>=1;
        }return r;
    }
    signed main(){
        freopen("count.in","r",stdin);
        freopen("count.out","w",stdout);
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=m;i++)scanf("%lld",&a[i]);
        jy.a[0][0]=1;cng.Ch(),cng2.Ch2();
        for(int i=1;i<=m;i++)jy=(jy*(cng^(a[i]-a[i-1]-1)))*cng2;
        jy=jy*(cng^(n-a[m]));
        printf("%lld
    ",jy.a[0][2]);
    }

    满满的智障气息.

  • 相关阅读:
    maven第三章 maven使用入门
    各个软件产生的原因
    maven的pom.xml深入理解
    批量同步订单信息(包括状态)到订单中心心得
    数据库连接超时和go away、如何检测数据库的最大连接数
    记录错误日志的技巧
    架构思想总结同步和事务的具体应用
    业务逻辑复杂性处理
    日志系统总结
    php捕获异常的处理
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/7028514.html
Copyright © 2011-2022 走看看