zoukankan      html  css  js  c++  java
  • 2017-7-10测试

    七天使的通讯

    时间限制: 2 Sec  内存限制: 256 MB
    提交: 412  解决: 120
    [提交][状态][讨论版]

    题目描述

    n个天使排成一条直线,某些天使之间需要互相联系,他们之间的通讯可以通过黑白两种通道中的一种;所有通道必须在直线同侧(另一侧是地面);为了保证通讯效率,同种颜色的所有通道之间不能相交。请计算能否建立这种通讯方案。

    输入

        第一行一个数T,表示接下来有T个询问。
        对于每个询问:第一行两个数n,m,分别表示有n个天使、需要建立通讯线路的天使有m对;接下来有m行,每行两个数a、b,表示a、b两个天使需要通讯。

    输出

    对于每个询问,输出一行“sane”表示有可行方案、“non”表示无解

    样例输入

    1
    7 5
    1 3
    2 7
    3 4
    7 4
    6 5
    

    样例输出

    sane
    

    提示

    【样例解释】

    样例中共有一个询问。




    在(1,3)、(4,7)、(5,6)之间连黑色通道,在(2,7)、(3,4)之间连白色通道,每条通道都成功建立,且同种颜色的通道没有相交,所以输出sane。


    【数据规模和约定】

    对于 20%的数据,1<=n<=50,1<=m<=15

    对于 50%的数据,1<=n<=1000,1<=m<=300

    对于 100%的数据,1<=n<=5000,1<=m<=1000,1<=T<=10,1<=a<=n,1<=b<=n

    数据保证每对(a,b)不重复,且a不等于b

    【提示】

    当两条线路有一对相同的端点时,这两条线路不相交。

    也就是说,对于线路(a,b)和线路(c,d)(a<b且c<d),当且仅当a<c<b<d或者c<a<d<b时这两条线路相交。

    我们可以根据它给出来的连边条件来构造一个图,然后染色判断这个图是否有冲突(是否为二分图),若成功了,便可以。
    #include<cstdio> 
    #include<iostream> 
    #include<algorithm> 
    #include<cmath> 
    #include<cstring> 
    #include<string> 
    using namespace std;  
      
    int CAS,n,m,color[1007]; 
    int cnt,head[1007],next[2000007],rea[2000007]; 
    struct fzy 
    { 
        int l,r; 
    }a[1007]; 
      
    bool check(int i,int j) 
    { 
        if (a[i].r<=a[j].l||a[j].r<=a[i].l) return 0; 
        if (a[i].l<=a[j].l&&a[i].r>=a[j].r) return 0; 
        if (a[i].r<=a[j].r&&a[i].l>=a[j].l) return 0; 
        return 1; 
    } 
    void add(int u,int v) 
    { 
        cnt++; 
        next[cnt]=head[u]; 
        head[u]=cnt; 
        rea[cnt]=v; 
    } 
    void dfs(int u) 
    { 
        for (int i=head[u];i!=-1;i=next[i]) 
        { 
            int v=rea[i]; 
            if (color[v]==-1) 
            { 
                color[v]=color[u]^1; 
                dfs(v); 
            } 
        } 
    } 
    int main() 
    { 
        scanf("%d",&CAS); 
        while (CAS--) 
        { 
            cnt=0; 
            memset(head,-1,sizeof(head)); 
            memset(color,-1,sizeof(color)); 
            scanf("%d%d",&n,&m); 
            for (int i=1;i<=m;i++) 
            { 
                scanf("%d%d",&a[i].l,&a[i].r); 
                if (a[i].l>a[i].r) swap(a[i].l,a[i].r); 
                for (int j=1;j<i;j++) 
                    if (check(i,j)) 
                    { 
                        add(i,j); 
                        add(j,i); 
                    } 
            } 
            for (int i=1;i<=m;i++) 
                if (color[i]==-1) 
                { 
                    color[i]=0; 
                    dfs(i); 
                } 
            int flag=0; 
            for (int i=1;i<=m;i++) 
            { 
                for (int j=head[i];j!=-1;j=next[j]) 
                { 
                    int u=i,v=rea[j]; 
                    if (color[u]==color[v]) 
                    { 
                        flag=1; 
                        break; 
                    }    
                } 
                if (flag==1) break; 
            } 
            if (flag==1) printf("non
    "); 
            else printf("sane
    "); 
        } 
    } 

    问题 B: 都市环游

    时间限制: 1 Sec  内存限制: 512 MB
    提交: 253  解决: 88
    [提交][状态][讨论版]

    题目描述

    因为SJY干的奇怪事情过多,SJY收到了休假的通知,于是他准备在都市间来回旅游。SJY有一辆车子,一开始行驶性能为0,每过1时间行驶性能就会提升1点。每个城市的道路都有性能要求。SJY一共有t时间休息,一开始他位于1号城市(保证1号城市道路要求为0),他希望在n号城市结束旅程。每次穿过一条城市间的路会花费1时间,当然他也可以停留在一个城市不动而花费1时间。当且仅当车子的行驶性能大于等于一个城市,我们才能到达那里。SJY希望知道,旅游的方案模10086后的答案。(只要在某一时刻通过的道路存在一条不相同,就算不同的方案)

    输入

        第一行三个数n,m,t,表示有n个城市m条道路t时间。
        第二行n个数,hi表示第i个城市的道路性能要求。
    第三到m+2行,每行两个数u,v,表示城市u与城市v之间有一条单向道路连接(可能有重边)。

    输出

    包括一个数字,表示旅游的方案模10086。

    样例输入

    5 17 7
    0 2 4 5 3 
    1 2
    2 1
    1 3
    3 1
    1 4
    4 1
    4 5
    5 4
    5 3
    4 1
    2 1
    5 3
    2 1
    2 1
    1 2
    2 1
    1 3
    

    样例输出

    245
    

    提示

    【数据规模和约定】

        对于20%的数据,n<=10,t<=80;

        对于50%的数据,n<=30,t<=80;

        对于100%的数据,n<=70,m<=1000,t<=100000000,hi<=70。

      这道题一看觉得像矩阵乘法,但前几个时间内的矩阵是不断变化的,所以我们能预处理出前max_T的时间内的矩阵。因为(max_T<70),然后剩下就是一个矩阵乘法啦。

    #include<iostream> 
    #include<cstdio> 
    #include<algorithm> 
    #include<cstring> 
    #define rep(i,a,b) for(int i=a;i<=n;i++) 
    using namespace std; 
    #define N 75 
    int n,m,Time,City_level[N],Highest_time,f[75][75],ans[N][N],c[N][N],b[N][N],map[N][N][N]; 
    void init() 
    { 
        scanf("%d %d %d",&n,&m,&Time); 
        for(int i=1;i<=n;i++) 
        { 
            scanf("%d",&City_level[i]); 
            Highest_time=max(Highest_time,City_level[i]); 
        } 
        for(int tt=1;tt<=min(Time,Highest_time);tt++) 
        for(int i=1;i<=n;i++) 
        { 
            map[tt][i][i]=1; 
        } 
        for(int i=1;i<=m;i++) 
        { 
            int x,y; 
            scanf("%d %d",&x,&y); 
            for(int j=City_level[y];j<=min(Time,Highest_time);j++) 
            { 
                map[j][x][y]++; 
            } 
        } 
    } 
    void DP() 
    { 
        ans[1][1]=1; 
        f[0][1]=1; 
        for(int TT=1;TT<=min(Highest_time,Time);TT++) 
        { 
            memset(c,0,sizeof(c)); 
            rep(i,1,n) 
                rep(j,1,n) 
                    rep(k,1,n) 
                    { 
                        c[i][j]=(c[i][j]+ans[i][k]*map[TT][k][j])%10086; 
                    } 
                      
            rep(i,1,n) 
                rep(j,1,n) 
                    ans[i][j]=c[i][j];       
        } 
    } 
    void saowei() 
    { 
        Time-=Highest_time; 
        for(int i=1;i<=n;i++) 
            for(int j=1;j<=n;j++) 
            b[i][j]=map[Highest_time][i][j]; 
        while(Time) 
        { 
            if(Time%2==1) 
            { 
                memset(c,0,sizeof(c)); 
                for(int i=1;i<=n;i++) 
                    for(int j=1;j<=n;j++) 
                        for(int k=1;k<=n;k++) 
                            c[i][j]=(c[i][j]+ans[i][k]*b[k][j])%10086; 
                for(int i=1;i<=n;i++) 
                    for(int j=1;j<=n;j++) 
                        ans[i][j]=c[i][j]; 
                      
            } 
            memset(c,0,sizeof(c)); 
            for(int i=1;i<=n;i++) 
                for(int j=1;j<=n;j++) 
                    for(int k=1;k<=n;k++) 
                    { 
                        c[i][j]=(c[i][j]+b[i][k]*b[k][j])%10086; 
                    } 
            for(int i=1;i<=n;i++) 
                for(int j=1;j<=n;j++) 
                    b[i][j]=c[i][j];     
            Time/=2; 
        } 
        cout<<ans[1][n]<<endl; 
    } 
    int main() 
    { 
        init(); 
        DP(); 
        saowei(); 
    } 

    问题 C: 大水题

    时间限制: 1 Sec  内存限制: 512 MB
    提交: 199  解决: 24
    [提交][状态][讨论版]

    题目描述

        dzy 定义一个n^2 位的数的生成矩阵A 为一个大小为n*n 且Aij 为这个数的第i*n+j-n位的矩阵。
    现在dzy 有一个数n^2 位的数k,他想知道所有小于等于k 的数的n*n 生成矩阵有多少种。(如果不足n^2 位则补前缀零)

    输入

    第一行一个数n,第二行一个n^2 位的数k

    输出

    仅一行表示答案,答案可能很大,你只需输出答案对10^9 + 7 取模后的结果。

    样例输入

    2
    1000
    

    样例输出

    954
    

    提示

    【数据规模和约定】 

    对于30% 的数据n<=2

    对于100% 的数据n <=1000,且n为偶数

     

    【提示】

        如果两个生成矩阵在其中一个旋转180 度后可以重叠,则称这两个矩阵是相同的。

     这道题看题面基本看不懂,但看样列就可以明白,其实让我们求小于k的所有不同种类的数(所谓相同种类就是指相反(在k位)或相同)

    所以答案个数就是。(f[i,n]表示i这个数在k位下的反转后的数)

    令f[i][j][k]表示前i位数,是否紧贴着前i个数,前i个数反转后是否贴紧了后i个数(j=1表示没贴近,j=0表示贴近了;k=1表示没爆炸,k=0表示爆炸了)

    所以x=(j||a[i+1]>l),y=(l<a[n-i])||(L==a[n-i]&&k)

    f[i+1][x][y]+=f[i][j][k]

    还有一个坑,就是strlen写在循环里面每次都会计算,时间复杂度内len^2,TLE;

    #include<iostream> 
    #include<cstdio> 
    #include<algorithm> 
    #include<cstring> 
    using namespace std; 
    #define ll long long 
    ll ans,dan; 
    ll n,i,f[1000015][2][2],a[1000015],niyuan=500000004,mod=1000000007; 
    char str[1000005]; 
    int main() 
    { 
        scanf("%lld",&n);n*=n; 
        scanf("%s",str+1); 
        int len=strlen(str+1); 
        for(int i=1;i<=len;i++) 
        a[i]=str[i]-'0',ans=(ans*10+a[i])%mod;  
        f[0][0][1]=1; 
        for(int i=0;i<n;i++) 
            for(int j=0;j<=1;j++) 
                for(int k=0;k<=1;k++) 
                { 
                    if(!f[i][j][k]) continue; 
                    for(int l=0;l<=9;l++) 
                    if(j||a[i+1]>=l)  
                    { 
                          
                        int x=(j||a[i+1]>l),y=(l<a[n-i]||l==a[n-i]&&k); 
                        (f[i+1][x][y]+=f[i][j][k])%=mod; 
                    } 
                 }  
                  
        dan=(f[n][0][1]+f[n][1][1])%mod; 
        dan=(dan-f[n/2][1][1]-f[n/2][1][0]-f[n/2][0][1])%mod; 
        dan=dan*niyuan%mod; 
        ans=((ans-dan)%mod+mod)%mod;  
        cout<<ans<<endl; 
                   
                   
    } 
  • 相关阅读:
    卡特兰数
    hdu 1023 Train Problem II
    hdu 1022 Train Problem
    hdu 1021 Fibonacci Again 找规律
    java大数模板
    gcd
    object dection资源
    Rich feature hierarchies for accurate object detection and semantic segmentation(RCNN)
    softmax sigmoid
    凸优化
  • 原文地址:https://www.cnblogs.com/dancer16/p/7150154.html
Copyright © 2011-2022 走看看