2020-07-02 热身训练赛(二)

A.边权为lcm的最小生成树(HDU 5922)

题意:一共有n个节点,编号从1到n,若在两个节点之间连边,则边权为两节点权值的最小公倍数,求该图的最小生成树的边权之和。

解:每个节点加到树里,需要使添加的边权最小,每个数字与1的最小公倍数是这个数字本身,因此为最小边权,所以只需要将每个节点与节点1相邻即可。此时的答案最小,为2~n的和,即$\frac{(2+n)(n-1)}{2}$

#include<iostream>
#include<cstdio>
using namespace std;
long long n,ans;
int main(){
    int T;
    scanf("%d",&T);
    for(int Case=1;Case<=T;Case++){
        scanf("%lld",&n);
        ans=(2+n)*(n-1)/2LL;
        printf("Case #%d: %lld\n",Case,ans);
    }
    return 0;
}

 

B.HDU 5923

 

C.不等式(HDU 5924)

题意:给出两个整数$A,B(1\leq A\leq B\leq 10^{18})$,求出有哪些整数对$C,D(A\leq C,D\leq B)$,满足$\frac{A}{B} + \frac{B}{A} \leq \frac{C}{D} + \frac{D}{C}$。

解:把$\frac{A}{B}$看作一个整体,为w,$\frac{C}{D}$也看作一个整体v(假设$C\geq D$,如果$D\geq C$,那么就令$v=\frac{D}{C}$,实际上都是一个道理),那么不等式可以写为$w+\frac{1}{w} \leq v+\frac{1}{v}$,因为C和D是A和B之间的值,所以$w\geq v$,且$w,v\geq 1$,由对号函数的图像可知,始终存在$w+\frac{1}{w}\geq v+\frac{1}{v}$,所以只有当$w=v$时有$w+\frac{1}{w}\leq v+\frac{1}{v}$,此时有$A=C,B=D或者A=D,B=C$。

#include<iostream>
#include<cstdio>
using namespace std;
int T;
long long A,B;
int main(){
    scanf("%d",&T);
    for(int Case=1;Case<=T;Case++){
        printf("Case #%d:\n",Case);
        scanf("%lld%lld",&A,&B);
        if(A==B){
            puts("1");
            printf("%lld %lld\n",A,B);
        }
        else {
            if(A>B)swap(A,B);
            puts("2");
            printf("%lld %lld\n%lld %lld\n",A,B,B,A);
        }
    }
    return 0;
}

 

D.连通块(HDU 5925)

题意:有个n*m的网格(长宽最大为$10^{9}$),有一些格子内有障碍(最多200个),问有多少四连通块,每个连通块内的格子数

解:离散化,将行和列分开进行离散化,拿行来讲,就是每个有障碍的行都要抽出来,两个有障碍的行之间的空白行离散为1行,这样的一行有一个权值,就是它对应的原来的行数,同理,列也要这样离散,直到将网格图离散为最多200*200的大小,就可以bfs了,还要注意一点,一个障碍没有的情况容易出错,最好特判一下。这个题和19年12月csp的第二题好像,当时那个题也做出来了,就是代码写的好啰嗦(捂脸脸)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
#define maxn 210
using namespace std;
int T,num,px[maxn],py[maxn],cntx,cnty,ans,n,m;
long long wx[maxn*2],wy[maxn*2],q[maxn*maxn*4];
bool f[maxn*2][maxn*2];
map<int,int>ox;
map<int,int>oy;
struct point{
    int x,y;
}p[maxn];

void hx(){
    for(int i=1;i<=num;i++){
        if(px[i]==px[i-1])continue;
        if(i==1&&px[i]!=1){
            cntx++;
            wx[cntx]=px[i]-1;
        }
        if(i!=1&&px[i]!=px[i-1]+1){
            cntx++;
            wx[cntx]=px[i]-px[i-1]-1;
        }
        cntx++;
        wx[cntx]=1;
        ox[px[i]]=cntx;
    }
    if(px[num]!=n){
        cntx++;
        wx[cntx]=n-px[num];
    }
}

void hy(){
    for(int i=1;i<=num;i++){
        if(py[i]==py[i-1])continue;
        if(i==1&&py[i]!=1){
            cnty++;
            wy[cnty]=py[i]-1;
        }
        if(i!=1&&py[i]!=py[i-1]+1){
            cnty++;
            wy[cnty]=py[i]-py[i-1]-1;
        }
        cnty++;
        wy[cnty]=1;
        oy[py[i]]=cnty;
    }
    if(py[num]!=m){
        cnty++;
        wy[cnty]=m-py[num];
    }
}

void dfs(int x,int y){
    q[ans]+=wx[x]*wy[y];
    f[x][y]=1;
    if(x>1&&!f[x-1][y])dfs(x-1,y);
    if(y>1&&!f[x][y-1])dfs(x,y-1);
    if(x<cntx&&!f[x+1][y])dfs(x+1,y);
    if(y<cnty&&!f[x][y+1])dfs(x,y+1);
}

void init(){
    memset(f,0,sizeof(f));
    memset(q,0,sizeof(q));
    ans=0;
    cntx=0;
    cnty=0;
}

int main(){
    scanf("%d",&T);
    for(int Case=1;Case<=T;Case++){
        init();
        scanf("%d%d",&n,&m);
        scanf("%d",&num);
        if(num==0){
            int e=0;
        }
        if(num==0){
            ans=1;
            printf("Case #%d:\n",Case);
            printf("%d\n",ans);
            long long www=1LL*n*m;
            printf("%lld",www);
            puts("");
            continue;
        }
        for(int i=1;i<=num;i++){
            scanf("%d%d",&p[i].x,&p[i].y);
            px[i]=p[i].x;py[i]=p[i].y;
        }
        sort(px+1,px+num+1);
        sort(py+1,py+num+1);
        hx();hy();
        
        for(int i=1;i<=num;i++){
            int x=ox[p[i].x];
            int y=oy[p[i].y];
            f[x][y]=1;
        }
        
        for(int i=1;i<=cntx;i++){
            for(int j=1;j<=cnty;j++){
                if(!f[i][j]){
                    ans++;
                    dfs(i,j);
                }
            }
        }
        printf("Case #%d:\n",Case);
        printf("%d\n",ans);
        sort(q+1,q+ans+1);
        for(int i=1;i<ans;i++)printf("%lld ",q[i]);
        printf("%lld\n",q[ans]);
    }
    return 0;
}

 

 

E.连连看(HDU 5926)

题意:给出一个连连看的初始状态,判断能否连一次

解:只需要判断四面和内部是否有可以连的

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
int a[31][31];
bool flag;
map<int,bool>vis;
int main(){
    int T;
    int n,m;
    scanf("%d",&T);
    for(int Case=1;Case<=T;Case++){
        printf("Case #%d: ",Case);
        flag=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&a[i][j]);
        vis.clear();
        for(int i=1;i<=m;i++){
            if(vis[a[1][i]])flag=1;
            vis[a[1][i]]=1;
        }
        if(flag){puts("Yes");continue;}
        vis.clear();
        for(int i=1;i<=m;i++){
            if(vis[a[n][i]])flag=1;
            vis[a[n][i]]=1;
        }
        if(flag){puts("Yes");continue;}
        vis.clear();
        for(int i=1;i<=n;i++){
            if(vis[a[i][1]])flag=1;
            vis[a[i][1]]=1;
        }
        if(flag){puts("Yes");continue;}
        vis.clear();
        for(int i=1;i<=n;i++){
            if(vis[a[i][m]])flag=1;
            vis[a[i][m]]=1;
        }
        if(flag){puts("Yes");continue;}
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(a[i][j]==a[i-1][j]&&i>1)flag=1;
                if(a[i][j]==a[i+1][j]&&i<n)flag=1;
                if(a[i][j]==a[i][j-1]&&j>1)flag=1;
                if(a[i][j]==a[i][j+1]&&j<m)flag=1;
            }
        }
        if(flag){puts("Yes");continue;}
        if(!flag){puts("No");continue;}
    }
}

 

 

F.HDU 5927

 

G.HDU 5928

 

H.nand(HDU 5929)

题意:定义一种位运算nand,满足$\\ 0 nand 0=1 \\ 0 nand1=1 \\ 1 nand 0=1 \\ 1 nand 1=0\\ $。要求实现一个栈,可以向栈顶加元素(只为1或0),弹出栈顶元素,求从栈顶到栈底的元素nand和,把栈反转,每次查询要求输出nand和。

解:用队列代替栈,反转操作就定义一个标记,把标记的1和0作为此时栈正或反的状态,添加元素和弹出元素就可以根据标记值决定加在队列头或者尾。求nand和时先看一下规律,发现再nand运算下,所有数字nand 0都得1,那么对于一个序列,从头nand过来,不管前面的值为多少,只要读到0,当前结果就为1。所以计算时只需要找到最后一个0的位置,把它当作1(如果只有一个0,而且在栈顶,就需要特判)。然后又发现$\\ 1=1 \\ 1 nand 1=0 \\ 1 nand 1 nand 1=1 \\ 1 nand 1 nand 1 nand 1=0\\$可以发现奇数个1的nand和为1,偶数个1的nand和为0,就可以结合末尾1的个数来求总nand和了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define maxn 200010
using namespace std;
int q[maxn*2],id[maxn*2],qcnt[2],idcnt[2];
bool flag=1;
char s[10];
int main(){
    freopen("Cola.txt","r",stdin);
    int T,x,n;
    scanf("%d",&T);
    for(int Case=1;Case<=T;Case++){
        qcnt[1]=idcnt[1]=200002;
        qcnt[0]=idcnt[0]=200003;
        flag=1;
        printf("Case #%d:\n",Case);
        scanf("%d",&n);
        while(n--){
            scanf("%s",s);
            if(s[2]=='S'){
                scanf("%d",&x);
                if(flag)q[++qcnt[flag]]=x;
                else q[--qcnt[flag]]=x;
                if(x==0){
                    if(flag)id[++idcnt[flag]]=qcnt[flag];
                    else id[--idcnt[flag]]=qcnt[flag];
                }
            }
            else if(s[2]=='P'){
                if(q[qcnt[flag]]==0){
                    if(flag)idcnt[flag]--;
                    else idcnt[flag]++;
                }
                if(flag)qcnt[flag]--;
                else qcnt[flag]++;
            }
            else if(s[2]=='V'){
                flag=!flag;
            }
            else if(s[2]=='E'){
                if(qcnt[1]<qcnt[0]){
                    puts("Invalid.");
                }
                else if(qcnt[0]==qcnt[1]){
                    printf("%d\n",q[qcnt[0]]);
                }
                else if(idcnt[1]<idcnt[0]){
                    printf("%d\n",(qcnt[1]-qcnt[0]+1)%2);
                }
                else if(idcnt[1]-idcnt[0]==0&&q[qcnt[flag]]==0){
                    printf("%d\n",(qcnt[1]-qcnt[0])%2);
                }
                else{
                    printf("%d\n",(abs(qcnt[!flag]-id[idcnt[!flag]])+1)%2);
                }
            }
        }
    }
    return 0;
}

 

 

I.HDU 5930

J.HDU 5931

K.HDU 5932

posted @ 2020-07-02 21:24  Echo宝贝儿  阅读(284)  评论(0编辑  收藏  举报