浙江大学第十九届图森未来杯大学生程序设计竞赛

赛后总结:

 T:这是我们第二次集体去参加学校的比赛,总体来说比上一次去浙江中医药校赛成绩好一点,也算是看到了我们自己的进步?然后呢,今天比赛,我们分头看了三道签到题,E J G,然后彭彭和金姐飞快的A了起来,我。。。看E看了好几遍才看懂。因为太紧张了,所以看到别人A那么快,然后就很想快速读懂题意。然后就开始看别的,直到彭彭和我们说A有点像二分图匹配,然后就开始看A了,然后我们想了一下,m那么大不可能是二分图,就想别的办法。最后和金姐讲了我的思路,然后就开始操作。于是看起了B,接收到题目意思有点问题,想了快两个小时也没想出来。期间金姐也在疯狂A提交。崩溃啊。然后就看了C,这题也有很多读题误区,金姐开始写了。我再读了一遍B,发现题意和我之前想的不一样。。。。啊啊啊然后就和队友说了,我们就想板子模拟大数中。最后没时间了,啥都没做出来。赛后队内总结了经验,交流一下以后读题的分工,还是很有收获的一场比赛。emmm,加油吧。

 J:今天前三题十分顺利,但是在A题上掉进了自己作的坑,疯狂WA,还好最后A出来了。C题感觉能写出来,可是时间不够了,哭~~~还是实力太弱了,继续努力,下次加油!

   P:看J时,浏览前几行后发现跟素数有关,数据范围还特别大就放弃了(其实真正的题目在最后三四行)翻了前面的题目。看了榜,发现J题A的很多,重新看回J题才发现真的是道水题,我就直接做了。接着,跟榜看了A,以为是二分图匹配(然而并不是),就误导了队友,庆幸我的队友不像我……接着帮金姐找A题样例,找了有、、久,但金姐还是A了!剩下两个小时,B,C全都有或多或少的题目理解错误问题,僵持了很久。后来,在谭总的纠正下,我似乎想出了B题,但来不及了,第一次遗憾。

 

题解:

 

A - Thanks, TuSimple!

 ZOJ - 4090 

题意:有n个男孩和m个女孩,他们要组成舞伴,双方有身高要求,0表示希望对方比自己矮,1表示希望对方比自己矮。问最后可以组成几对。

思路:分成4大组。男选1和女选0对应,男选0和女选1对应。看代码就能懂啦。

#include 
#include
using namespace std;

#define inf 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define ll long long
#define MAXN 1001000
#define mod ((int)1e9+7)
const int N=1e5+50;
using namespace std;
typedef long long int LL;

int work(vector<int>& p,vector<int>& q)
{
    int ans=0;
    sort(p.begin(),p.end());
    sort(q.begin(),q.end());
    while(!p.empty()&&!q.empty())
    {
        if(p.back()>q.back())
            p.pop_back(),ans++;
        q.pop_back();
    }
    return ans;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d %d",&n,&m);
        vector<int>boy,gril;
        int h;
        for(int i=0;i)
        {
            scanf("%d",&h);
            boy.push_back(h);
        }
        for(int i=0;i)
        {
            scanf("%d",&h);
            gril.push_back(h);
        }
        vector<int>p[2],q[2];
        int qq;
        for(int i=0;i)
        {
            scanf("%d",&qq);
            p[qq].push_back(boy[i]);
        }
        for(int i=0;i)
        {
            scanf("%d",&qq);
            q[qq].push_back(gril[i]);
        }
        printf("%d\n",work(p[0],q[1])+work(q[0],p[1]));
    }
    return 0;
}
View Code

 

B - Even Number Theory

 ZOJ - 4091 

 

import java.util.*;
import java.math.*;
public class Main {
    public static void main(String[] args) {
        Scanner cin=new Scanner(System.in);
        int T;
        T=cin.nextInt();
        while(T>0)
        {
            T--;
            BigInteger num,ans = BigInteger.valueOf(0);
            num=cin.nextBigInteger();
            while(num.compareTo(BigInteger.valueOf(0))!=0)
            {
                num=num.divide(BigInteger.valueOf(2));
                ans=ans.add(num);
            }
            System.out.println(ans);
        }
    }
}

 

C - Robot Cleaner I

 ZOJ - 4092 

题意:给一个n*m的数字地图,1表示墙壁,2表示垃圾,0表示空的,还有六种命令,U是向上,D是向下,R向右,L向左,P扫地,I表示什么都不做。

  下指令是这样的,首先获取当前位置的坐标(x,y),然后计算一个式子。

  x = 3 * 3 * 3 * 3 * mapp[x][y] + 3 * 3 * 3 * mapp[x - 1][y] + 3 * 3 * mapp[x + 1][y] + 3 * mapp[x][y - 1] + mapp[x][y + 1];

  然后执行第x+1个指令。(指令从1开始存哦)

  在k步内会结束所有操作,然后输出捡了多少垃圾。

  指令s是有限的,但是k比较大,处于1~10^18。所以如果出现相同的指令或者处于当前位置捡垃圾数量相同的就说明出现循环了,跳出就可以了。

#include
#include
#include
#include
#include
#include
#include<set>
#include<string>
#include
#include
#include
using namespace std;
#define inf 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define ll long long
#define MAXN 1001000
#define mod ((int)1e9+7)
const int N=751;
using namespace std;
typedef long long LL;
char mmap[2050][2050];
int mapp[2050][2050];
int n,m,a,b,k,ans;
char s[300];
int vis[2050][2050][2];
int Cal(int x,int y)
{
    int xx = 3 * 3 * 3 * 3 * mapp[x][y] + 3 * 3 * 3 * mapp[x - 1][y] + 3 * 3 * mapp[x + 1][y] + 3 * mapp[x][y - 1] + mapp[x][y + 1];
    return xx;
}

void dfs(int x,int y)
{
    if(k==0) return;
    int pos=Cal(x,y);
    char p=s[pos+1];
    if(vis[x][y][1]==ans&&vis[x][y][0]==pos)
        return;
    vis[x][y][0]=pos;
    vis[x][y][1]=ans;
    if(p=='U')
    {
        if(mapp[x-1][y]!=1)
            x--;
    }
    else if(p=='D')
    {
        if(mapp[x+1][y]!=1)
            x++;
    }
    else if(p=='L')
    {
        if(mapp[x][y-1]!=1)
            y--;
    }
    else if(p=='R')
    {
        if(mapp[x][y+1]!=1)
            y++;
    }
    else if(p=='P')
    {
        if(mapp[x][y]==2)
        {
            ans++;
            mapp[x][y]=0;
        }
    }
    else if(p=='I') return;
    k--;
    dfs(x,y);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ans=0;
        scanf("%d %d",&n,&m);
        scanf("%d %d %d",&a,&b,&k);
        scanf("%s",s+1);
        for(int i=1;i<=n;i++)
        {
            getchar();
            for(int j=1;j<=m;j++)
            {
                scanf("%c",&mmap[i][j]);
                mapp[i][j]=mmap[i][j]-'0';
                vis[i][j][0]=vis[i][j][1]=-1;
            }
        }
        dfs(a,b);
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

E - Potion

 ZOJ - 4094 

签到题。题意大致为,制药需要的材料,一共n种,每种需要的材料为a数组,而baobao拥有的材料为b数组。高级材料可以降级为低级材料,有无限次转换的机会。问最后可不可以制成药。

方法:遍历第一个到倒数第二个,第i个所需要的材料从i+1索取,然后看最后一组满不满足条件即可。

#include
#include
#include
#include
#include
#include
#include<set>
#include
#include<string>
#include
#include
#include
using namespace std;
#define inf 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define ll long long
#define MAXN 101000
#define mod ((int)1e9+7)
int n, k;
int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        ll a[200], b[200];
        scanf("%d", &n);
        for (int i = 0; i < n; i++)
            scanf("%lld", &a[i]);
        for (int i = 0; i < n; i++)
            scanf("%lld", &b[i]);
        for (int i = 0; i < n - 1; i++)
        {
            if (a[i] - b[i] > 0)
                b[i + 1] = b[i+1]-(a[i] - b[i]);
        }
        if (b[n - 1] >= a[n - 1]) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
View Code

 

G - Postman

 ZOJ - 4096 

题意:BaoBao要送信,一次能最多拿K封,给你几个坐标,有正也有负,拿完以后需要回到0点重新拿。问最后最少的距离是多少。

解法:把正坐标和负坐标分开存储,0点不用管。排序以后,每个数组每次取k封信,距离加上绝对值最大的*2,因为他寄完之后不需要回到原点,就减去最远的距离。

#include 

using namespace std;

#define inf 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define ll long long
#define MAXN 1001000
#define mod ((int)1e9+7)
const int N=1e5+50;
using namespace std;
typedef long long int LL;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,k;
        scanf("%d %d",&n,&k);
        vector<int> pos,neg;
        int maxx=0;
        ll ans=0;
        for(int i=0;i)
        {
            int num;
            scanf("%d",&num);
            maxx=max(maxx,(int)abs(num));
            if(num>0)
                pos.push_back(num);
            else if(num<0)
                neg.push_back(-num);
        }
        sort(pos.begin(),pos.end(),greater<int>());
        sort(neg.begin(),neg.end(),greater<int>());
        for(int i=0;ik)
        {
            //cout<
            ans+=pos[i]*2;
        }
        for(int i=0;ik)
        {
            //<
            ans+=neg[i]*2;

        }
        ans-=maxx;
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

 

J - Extended Twin Composite Number

 ZOJ - 4099 

题意:给一个正整数n,求两个合数x,y,满足x+n=y。

解法:我的想法很傻,从i=4开始遍历,然后满足x和y不是素数就好了。。。队友和我说,如果n是偶数的时候,x=4就好了,n是奇数的话,x=9就可以了。

#include 

using namespace std;

#define inf 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define ll long long
#define MAXN 1001000
#define mod ((int)1e9+7)
const int N=751;
using namespace std;
typedef long long int LL;

bool isnotprime(ll num)
{
    ll a=sqrt(num);
    for(ll i=2;i<=a;i++)
    {
        if(num%i==0)
            return true;
    }
    return false;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ll n;
        scanf("%lld",&n);
        ll a=4,b;
        for(;a<=100;a++)
        {
            b=n+a;
            //cout<
            if(isnotprime(b)&&isnotprime(a))
                break;
        }
        printf("%lld %lld\n",a,b);
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/Tangent-1231/p/10707044.html

你可能感兴趣的:(浙江大学第十九届图森未来杯大学生程序设计竞赛)