zoukankan      html  css  js  c++  java
  • 2017年浙江工业大学大学生程序设计迎新赛决赛题解

    【题目链接】:https://www.nowcoder.com/acm/contest/63#question

     【暴力题】


    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 131072K,其他语言262144K
    64bit IO Format: %lld

    题目描述

            栗酱突发闲心,玩了一会儿仙剑。
            她玩的这个版本的仙剑非常简单,打架的时候,每次只有一个小怪,栗酱也只有一个主角,主角在每回合开始先攻击小怪,小怪有a点生命值,主角有b点生命值,小怪有c点攻击力,主角有d点攻击力,每次攻击都会造成确确实实的攻击力的伤害。
            生命值小于等于零时就会挂掉。
            栗酱发现好像战斗一开始就已经能知道结果了,请你帮她算一下,这样她就可以挂机去做更有趣的事了。
            数据保证攻击力和初始生命值均大于等于1。

    输入描述:

    第一行一个数据组数T。
    每组数据一行4个整数a,b,c,d,数据之间用一个空格隔开。

    输出描述:

    对于每组数据每行给出一个"Yes"或"No",代表栗酱能否取得胜利。
    示例1

    输入

    2
    1 2 3 4
    84 3 23 6

    输出

    Yes
    No

    说明

    样例1解释:
    第一回合时栗酱先发动攻击,小怪的生命值:1−4≤0,所以栗酱取得了胜利。

    备注:

    T≤1000,
    1≤a,b,c,d≤1000
    【代码】:
    #include <bits/stdc++.h>
    
    using namespace std;
    
    int a,b,c,d;
    int t;
    bool f;
    int main()
    {
        scanf("%d",&t);
        while(t--){
            scanf("%d%d%d%d",&a,&b,&c,&d);
            while(1)
            {
                a-=d;
    
                if(a<=0){
                    f=true;//win
                    break;
                }
                b-=c;
    
                if(b<=0){
                    f=false;
                    break;
                }
            }
            if(f){
                puts("Yes");
            }
            else{
                puts("No");
            }
        }
    
    
    }

    题目描述

            “伟大的勇栗兔栽栗女王,所有栗子看到您都不寒而栗,但也非常尊重您。您骑着威风凛凛的小白兔,带领栗子们奋勇前行。伟大史诗告诉我们,烈兔勇栗从大草原飞奔出来,
    冲在每场战争的前线——无论您在哪里,他们都能找到您。骑小白兔飞驰吧,凶猛的女王,但愿您有真正的朋友和软弱的敌人。”
    今天,冰雪聪明的栗酱终于玩到了她梦寐很久的文明游戏。
    不过作为一个萌新,兔头獐脑的栗酱自然不愿意第一次玩就遇到一个尴尬的结局,于是希望通过你来寻找一个完美结局。

            已知游戏结束前场上有n个国家,第i个国家有ai块土地,任意2个国家若是想建立外交关系,则需要互相在对方的一块土地上建立一个大使馆。
    一块土地只能建立一个大使馆,若一个国家和其他国家存在外交关系,则需要征用一块己方土地作为备用大使馆。
            完美结局的定义是:找到最多数量的国家,使他们相互之间存在外交关系。

    输入描述:

    第一行一个数T,表示有T组数据。
    对于每组数据,第一行输入一个数n,表示国家的数量,接下来一行输入n个数,a1,a2,…,an,其中ai表示第i个国家拥有的土地数量。每两个相邻的数之间用空格隔开。

    输出描述:

    对于每一个询问,输出一个数,即完美结局下,相互建立外交关系的国家数量。
    示例1

    输入

    2
    5
    2 2 2 2 2
    10
    8 6 5 9 2 7 10 3 3 9

    输出

    2
    6

    说明

    对于第一个样例:
    最多只能找到2个国家,使他们互相建立外交关系。
    对于第二个样例:
    第1,2,4,6,7,10个国家间可互相建立外交关系,最多数量为6。

    备注:

    T≤10
    1≤n≤1000
    1≤ai≤n
     
    #include <bits/stdc++.h>
    
    using namespace std;
    const int N = 1010;
    int n,a[N];
    int t,ans,j;
    bool f;
    int main()
    {
        scanf("%d",&t);
        while(t--){
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            sort(a+1,a+n+1);
    
            for(int i=n,j=0; i>=1; i--,j++){
                a[i]-=j;
                //printf("i=%d,j=%d,a[i]=%d
    ",i,j,a[i]);//
                if(a[i]<=0){
                    ans=j;
                    break;
                }
            }
            printf("%d
    ",ans);
        }
    }
    模拟

    题目描述

            栗酱一个人闲得无聊的时候总是会一个人玩一些有趣的游戏。
            有一天,她在机房里看见了一张图,可能是做acm的学长留下的:

            栗酱想知道每一个数字,横着竖着分别有几根火柴呢?(由于火柴商偷工减料,我们认定,只要存在棍子,它就是火柴!)

    输入描述:

    第一行一个数据组数T。
    每组数据一行给出一个数字'a'。

    输出描述:

    对于每个数字给出两个值,分别是横着有几根火柴,竖着有几根火柴。
    示例1

    输入

    1
    0

    输出

    2 4
    #include <bits/stdc++.h>
    #include <map>
    
    using namespace std;
    const int N = 1010;
    int n;
    int t,ansx,ansy;
    string s;
    map<int, pair<int,int> >mp;
    //不能在全局初始化STL
    int x;
    int main()
    {
            mp[0].first=2;
            mp[0].second=4;
    
            mp[1].first=0;
            mp[1].second=2;
    
            mp[2].first=3;
            mp[2].second=2;
    
            mp[3].first=3;
            mp[3].second=2;
    
            mp[4].first=1;
            mp[4].second=3;
    
            mp[5].first=3;
            mp[5].second=2;
    
            mp[6].first=3;
            mp[6].second=3;
    
            mp[7].first=1;
            mp[7].second=2;
    
            mp[8].first=3;
            mp[8].second=4;
    
            mp[9].first=3;
            mp[9].second=3;
        scanf("%d",&t);
        while(t--){
           cin>>s;
           for(int i=0; i<s.size(); i++){
             ansx += mp[ ((s[i]-'0')%10) ].first;
             ansy += mp[ ((s[i]-'0')%10) ].second;
             x=s[i]-'0';
             x/=10;
           }
           printf("%d %d
    ",ansx,ansy);
           //mp.clear();
           ansx=ansy=0;
    
        }
    }
    模拟

    【基础算法题】


    题目描述

    给定两个长度为n的整数列A和B,每次你可以从A数列的左端或右端取走一个数。假设第i次取走的数为ax,则第i次取走的数的价值vi=bi⋅ax,现在希望你求出∑vi的最大值。

    输入描述:

    第一行一个数T,表示有T组数据。
    对于每组数据,第一行一个整数n,
    接下来两行分别给出A数列与B数列。

    输出描述:

    每一组数据输出一行,最大的∑vi。
    示例1

    输入

    2
    2
    1 1000
    2 1
    5
    1 3 5 2 4
    1 2 3 4 5

    输出

    2001
    52

    说明

    对于第二个样例,
    第一次从左边取走a1,v1=a1⋅b1=1,
    第二次从左边取走a2,v2=a2⋅b2=6,
    第三次从右边取走a5,v3=a5⋅b3=12,
    第四次从右边取走a4,v4=a4⋅b4=8,
    第五次取走剩下的a3,v5=a3⋅b5=25。
    总价值∑vi=1+6+12+8+25=52

    备注:

    T≤10
    1≤n≤103
    1≤ai,bi≤103
    【分析】:基本区间DP。
    【相似】:http://tyvj.joyoi.cn/Solution/6645    https://www.cnblogs.com/yangqingli/p/4735607.html  https://www.cnblogs.com/EdSheeran/p/6701200.html
    【代码】:
    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<math.h>
    #include<time.h>
    #include<stdlib.h>
    #include<queue>
    #include<stack>
    #include<set>
    #include<map>
    #include<vector>
    #include<algorithm>
    #define INF 0x3f3f3f3f
    using namespace std;
    int a[1010],b[1010];
    int dp[1010][1010];
    int dfs(int l,int r,int time)
    {
        if(l>r)return 0;
        if(dp[l][r])return dp[l][r];
        int temp=0;
        temp=max(temp,dfs(l+1,r,time+1)+b[time]*a[l]);
        temp=max(temp,dfs(l,r-1,time+1)+b[time]*a[r]);
        return dp[l][r]=temp;
    }
    int main()
    {
        int t,n;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            memset(dp,0,sizeof(dp));
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            for(int i=1;i<=n;i++)
                scanf("%d",&b[i]);
            printf("%d
    ",dfs(1,n,1));
        }
        return 0;
    }
    dp

    题目描述

    栗酱有一个长度为n的数列A,一个长度为m的数列B,现在询问A中有多少个长度为m的连续子序列A',
    满足(a'1+b1)%k = (a'2+b2)%k = …… = (a'm + bm)%k。

    输入描述:

    第一行一个数T,表示有T组数据。
    对于每组数据,
    第一行三个整数,n, m, k。
    第一行输入n个数, a1,a2,…,an, 表示A数列中的数,
    第二行输入m个数, b1,b2,…,bm, 表示B数列中的数。

    输出描述:

    每一组数据输出一行,满足条件的连续子序列数量。
    示例1

    输入

    2
    3 2 5
    7 8 7
    8 7
    3 2 5
    7 8 9
    8 7

    输出

    1
    2

    备注:

    T≤15,
    2≤m≤n≤2×105,
    1≤ai,bi,k≤109
    【分析】:kmp/暴力匹配
    【代码】:
    #include<bits/stdc++.h>
    using namespace std;
    int a[200005],b[200005];
    int main()
    {
        
        int T;
        int n, m, k, i, j;
        scanf("%d", &T);
        while(T--)
        {
            int count=0;
            scanf("%d%d%d", &n, &m, &k);
            for(i=0;i<n;i++)
                scanf("%d", &a[i]);
            for(i=0;i<m;i++)
                scanf("%d", &b[i]);
            for(i=0;i<n;i++)
            {
                 for(j=0;j<m-1;j++)
                 {
                     if((a[i+j]+b[j])%k==(a[i+j+1]+b[j+1])%k)
                         continue;
                     else
                         break;
                 }
                 if(j==m-1)
                     count++;
            }
            printf("%d
    ", count);
        }
        return 0;
    }
    暴力匹配
    #include <bits/stdc++.h>
    using namespace std;
    #define clr(a, x) memset(a, x, sizeof(a))
    #define mp(x, y) make_pair(x, y)
    #define pb(x) push_back(x)
    #define X first
    #define Y second
    #define fastin                    
        ios_base::sync_with_stdio(0); 
        cin.tie(0);
    typedef long long ll;
    typedef long double ld;
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-6;
     
    // 返回y中x的个数
    const int N = 1 << 18;
    int Next[N];
    void initkmp(int x[], int m)
    {
        int i = 0, j = Next[0] = -1;
        while (i < m)
        {
            while (j != -1 && x[i] != x[j]) j = Next[j];
            Next[++i] = ++j;
        }
    }
    int kmp(int x[], int m, int y[], int n)
    {
        int i, j, ans;
        i = j = ans = 0;
        initkmp(x, m);
        while (i < n)
        {
            while (j != -1 && y[i] != x[j]) j = Next[j];
            i++, j++;
            if (j >= m) ans++, j = Next[j];
        }
        return ans;
    }
     
    int a[N], b[N];
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("1.in", "r", stdin);
        freopen("1.out", "w", stdout);
    #endif
        int T;
        scanf("%d", &T);
        while (T--)
        {
            int n, m, k;
            scanf("%d%d%d", &n, &m, &k);
            for (int i = 0; i < n; i++) scanf("%d", &a[i]);
            for (int i = 0; i < m; i++) scanf("%d", &b[i]);
            for (int i = 0; i < n; i++) a[i] %= k;
            for (int i = 0; i < m; i++) b[i] = (k - b[i] % k) % k;
            for (int i = 0; i < n - 1; i++) a[i] = (a[i + 1] - a[i] + k) % k;
            for (int i = 0; i < m - 1; i++) b[i] = (b[i + 1] - b[i] + k) % k;
            printf("%d
    ", m - 1 ? kmp(b, m - 1, a, n - 1) : n);
        }
        return 0;
    }
    kmp

    题目描述

    有不等式y⋅x3≤ n,已知y为正整数,x为大于1的正整数,问当x和y的解数量刚好为m的时候n的最小值,如果不存在输出 -1。

    输入描述:

    多组数据读入。
    每组数据一个数字m,如题所示。

    输出描述:

    每组数据输出一行,输出答案。
    示例1

    输入

    1

    输出

    8

    说明

    当方案恰好只有一种的时候,n的最小值为8,此时y=1,x=2。

    备注:

    1 ≤ m ≤ 1016

    【分析】:找满足某条件check(n)的最小/最大的x可用二分搜索某可行解。

    【代码】:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    
    ll check(ll cnt)
    {
        ll ans=0;
        for(ll x=2; x*x*x<=cnt; x++) ans+=cnt/(x*x*x);
        return ans;
    }
    int main()
    {
        ll m;
        while(~scanf("%lld",&m)){//记得~!!!
        ll l=1,r=1e16,mid;
        while(l<=r){
            mid=(l+r)/2;
            if(check(mid)>=m)
                r=mid-1;
            else
                l=mid+1;
        }
        printf("%lld
    ",check(l)==m?l:-1);
        }
    }
    二分搜索可行解
  • 相关阅读:
    (转)关于IBM小机P520的面板使用
    (转)mysql的sql_mode合理设置
    (转)Mysql技术内幕InnoDB存储引擎-事务&备份&性能调优
    杨辉三角
    异或的陷阱(转)
    通过数组看栈堆
    数组的一些知识点和插入选择冒泡排序
    运算符
    Java的变量相关
    有符号的数据表示法(原、反、补)
  • 原文地址:https://www.cnblogs.com/Roni-i/p/8093120.html
Copyright © 2011-2022 走看看