“亚信科技杯”南邮第七届大学生程序设计竞赛之网络预赛 (部分题解)

限时加码!20+主流AI编程工具免费用 购周边加赠Coding Plan Lite,Claude Code、Cursor等即刻畅享,学习进阶更高效! 阅读详情

“亚信科技杯”南邮第七届大学生程序设计竞赛之网络预赛


比赛链接http://acm.njupt.edu.cn/acmhome/contest.do?&method=contestDetail&contestId=215 FFF



 FFF
时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 130            测试通过 : 9

题目描述
FFF团,一个异端审判组织,团员活跃在各个角落,每当烧烤节来临的时候,我们都能听到他们传播的那熟悉的旋律:
烧啊~烧啊~烧啊烧啊烧~ (请自行脑补《当》)
FFF团成员自带这样一个属性:凭空变出火把与汽油,两者配合起来才能让FFF之火duang的一下烧起来,但是不同的火把与不同的汽油配合产生的火焰是不同的,现在有n种火把与n种汽油,已知每一种火把与每一种汽油配合时产生的火焰的旺盛程度,现在求怎样使得火把与汽油一一配对,产生最旺盛的火焰。

输入
第一行为一个整数T,表示有T组数据
每组数据第一行为一个正整数n(2≤n≤30)
第二行开始一共有n行,每行为n个正整数,第i行第j个数表示第i种火把与第j种汽油配合的火焰的旺盛程度。(0<a[i][j]≤10000)

输出
每组数据输出一个整数,表示最大的火焰旺盛程度

样例输入
2
3
5 2 6
6 7 9
7 4 1
4
8 5 2 8
5 8 2 1
9 6 3 7
7 5 8 1

样例输出
20
33

题目来源
kojimai


题目分析:开始没多久就被秒掉的题。。。果然是个裸模板,二分图带权最大匹配,套一个km的板子就行了,km算法就不在这说了


#include <cstdio>
#include <cstring>
int const MAX = 50;
int const INF = 0x3fffffff;

int n, nx, ny;
int link[MAX], lx[MAX], ly[MAX], slack[MAX];
int visx[MAX], visy[MAX], w[MAX][MAX];

int DFS(int x)
{
    visx[x] = 1;
    for(int y = 1; y <= ny; y++)
    {
        if(visy[y])
            continue;
        int t = lx[x] + ly[y] - w[x][y];
        if(t == 0)      
        {
            visy[y] = 1;
            if(link[y] == -1 || DFS(link[y]))
            {
                link[y] = x;
                return 1;
            }
        }
        else if(slack[y] > t) 
            slack[y] = t;
    }
    return 0;
}

int KM()
{
    memset(link, -1, sizeof(link));
    memset(ly, 0, sizeof(ly));
    for(int i = 1; i <= nx; i++)  
    {
        lx[i] = -INF;          
        for(int j = 1; j <= ny; j++)
            if(w[i][j] > lx[i])
                lx[i] = w[i][j];
    }
    for(int x = 1; x <= nx; x ++)
    {
        for(int i = 1; i <= ny; i ++)
            slack[i] = INF;
        while(true)
        {
            memset(visx, 0, sizeof(visx));
            memset(visy, 0, sizeof(visy));
            if(DFS(x))    
                break;  
            int d = INF;
            for(int i = 1; i <= ny; i++)
                if(!visy[i] && d > slack[i])
                    d = slack[i];
            for(int i = 1; i <= nx; i++)
                if(visx[i])
                    lx[i] -= d;
            for(int i = 1; i <= ny; i++) 
                if(visy[i])
                    ly[i] += d;
                else
                    slack[i] -= d;
        }
    }
    int res = 0;
    for(int i = 1; i <= ny; i++)
        if(link[i] > -1)
            res += w[link[i]][i];
    return res;
}

int main ()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        nx = ny = n;
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                scanf("%d", &w[i][j]);
        int ans = KM();
        printf("%d\n", ans);
    }
}




 pdf的旅游

时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 100            测试通过 : 21


题目描述

a协有一位pdf是一位旅(作)游(死)爱好者,曾经在出去比赛之后拐带学弟翘课一周,四处旅游。
最近pdf又突发奇想,想再出去旅游一次。出去旅游之前当然要好好计划一番。Pdf给自己想去的地方并给它们编好了号(起点为1)。为了不跟自己过不去,pdf提前找出哪些地点存在交通方便的路径,而且只会走这些路径。
为了旅途乐趣的最大化,pdf希望每个地点都到访过的同时,又保证来去都不会走重复的路,而且最终还要回到起点。问想要达到上述要求,pdf应该怎么样安排地点的访问顺序。

输入
第一行一个整数t,表示数据组数。
每组数据的第一行两个整数n,m分别表示地点数和路径数。(2≤n≤10,n≤m≤n(n-1)/2)
接下来的m行每行两个整数x,y 表示x,y之间交通方便。(保证两点之间只会有一条路)(1≤x,y≤n)

输出
每组数据输出一行,从起点开始的游览顺序。以空格分隔开。如果存在多解,则输出字典序最小的路径。(除起点外每个点只能访问一次)

样例输入
2
4 4
1 3
2 3
2 4
1 4

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

样例输出
1 3 2 4 1
1 2 3 5 4 1

题目来源
kojimai

题目分析:第一眼看以为是欧拉回路,拍完发现并不是,其实就是一道搜索题,其实因为n只有10,暴力就能过了,枚举全排列,模拟一下


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int flag[20][20];
int p[11];

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        memset(flag, 0, sizeof(flag));
        int n, m;
        scanf("%d %d", &n, &m);
        for(int i = 0; i < m; i++)
        {
            int a, b;
            scanf("%d %d", &a, &b);
            flag[a][b] = 1;
            flag[b][a] = 1;
        }
        for(int i = 0; i < n; i++)
            p[i] = i + 1;
        p[n] = 1;
        do
        {
            bool f = true, f2 = false;
            for(int i = 0; i < n; i++)
            {
                if(i == n - 1 && !flag[p[i]][1])
                {
                    f = false;
                    break;
                }
                if(i != n - 1 && !flag[p[i]][p[i + 1]] && !flag[p[i + 1]][p[i]])
                {
                    f = false;
                    break;
                }
            }
            if(f)
                break;
        }while(next_permutation(p, p + n));
        for(int i = 0; i < n; i++)
            printf("%d ", p[i]);
        printf("1\n");
    }
}


 

特技的幂
时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 481            测试通过 : 103


题目描述
幂运算是常见的数学运算之一,其原理是用同一个数相乘多次,但是有的时候当幂指数特别大的时候,这样的运算就太浪费时间。请大家学会在幂中加特技,让幂运算的效率提高到可以接受的程度。


输入
第一个行一个整数T,表示有T组数据
每组数据,输入x,y 求x的y次幂 (2≤ x ,y≤10^9)

输出
每组数据输出一个整数,表示幂运算对1000000007取模后的结果

样例输入
2
2 4
2 100000000

样例输出
16
494499948

题目来源
kojimai


题目分析:这。。。

#include <cstdio> 
#define ll long long
int const MOD = 1e9 + 7;  

ll quick_pow(ll a, ll b,ll m)
{
    ll d = 1, t = a;
    while(b > 0)
    {
        if(b % 2)
            d = (d * t)%m;
        b /= 2;
        t = (t * t) % m;
    }
    return d;
}
  
int main()   
{   
    int T;
    scanf("%d", &T);
    while(T--)
    {
        ll a, b;
        scanf("%I64d %I64d", &a, &b);
        printf("%I64d\n", quick_pow(a, b, MOD));
    }
} 


 天神小学
时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 145            测试通过 : 50


题目描述
《corpse party:blood drive》中有这么一段,班长筱崎亚由美拿到六鬼门的晶石,导致了涅?的暴走,天小的崩溃,靠着幸子的力量才逃出了天小。(剧情什么的不重要)
现在我们假设没有幸子,班长需要靠自己的力量逃出天神小学。可以把天神小学看作是一个二维的迷宫,每一秒都只能从当前位置走到上下左右四个相邻的格子里,因为天小一直在崩溃,所以有很多点是无法行走的。问班长能不能在天小完全崩溃,即t秒内逃出天神小学。

输入
第一行一个整数T,表示数据组数
每组数据第一行输入3个整数n,m,t分别表示迷宫的行数,列数,以及距离天小崩溃剩余的时间。(3≤n,m≤20,t≤100)
接下来输入n行,每行有一个长度为m的字符串。
其中字符’.’表示可以通行
字符’*’表示无法通行
字符’O’表示出口
字符’X’表示班长的起始位置

输出
若能逃离 输出 "happy end"
否则输出 "bad end"

样例输入
2
5 5 13
.....
.***.
.*X*O
.*.*.
...*.

5 5 14
.....
.***.
.*X*O
.*.*.
...*.

样例输出
bad end
happy end

题目来源
kojimai


题目分析:应该找不到比这个更裸的BFS了。。。

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int const MAX = 25;
char map[MAX][MAX];
int vis[MAX][MAX];
int dirx[4] = {1,-1,0,0};   
int diry[4] = {0,0,-1,1};
int n, m, t;
int sx, sy, ex, ey;
struct Point
{
    int x, y;
    int step;
};

int BFS()
{
    memset(vis,0,sizeof(vis)); 
    queue<Point> q;
    Point node, t;
    node.x = sx;
    node.y = sy;
    node.step = 0;
    vis[sx][sy] = 1;
    q.push(node);   
    while(!q.empty())   
    {
        node = q.front();  
        q.pop();            
        for(int i = 0; i < 4; i++)  
        {
            t = node;
            t.x += dirx[i];
            t.y += diry[i];
            t.step++;
            if(t.x == ex && t.y == ey)   
                return t.step;
            if(t.x < 0 || t.x >= n || t.y < 0 || t.y >= m || map[t.x][t.y] == '*' || vis[t.x][t.y]) 
                continue;
            else
            {
                vis[t.x][t.y] = 1;
                q.push(t);
            }
        }
    }
    return 10000;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d %d %d",&n, &m, &t);
        for(int i = 0; i < n; i++)
        {
            scanf("%s", map[i]);
            for(int j = 0; j < m; j++)
            {
                if(map[i][j] == 'X')
                {
                    sx = i;
                    sy = j;
                }
                if(map[i][j] == 'O')
                {
                    ex = i;
                    ey = j;
                }
            }
        }
        int ans = BFS();
        if(ans <= t)
            printf("happy end\n");
        else
            printf("bad end\n");
    }
}

 

Dreaming

时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 88            测试通过 : 8


题目描述
我们定义一个数good当且仅当它只由a和b构成,且数位和sum各数位也仅由a和b构成。举个栗子:若a=1,b=2,那么13不是good,11是(都由a=1构成,数位和sum=2由b=2构成)。那么窝们定义一个数的长度为n,那么有多少个数是good呢?所求答案对10^9+7取模。

输入
多组样例。
每行包含三个数a,b,n(1<=a,b<=9,1<=n<=10^6)

输出
每组数据输出一个整数。

样例输入
1 3 3

样例输出
1


题目分析:首先我们求各种可能的和,然后分解判断是不是满足条件,接着求组合数就行了比如长度为10,3个a+7个b满足,则这种情况就有C(10,3)个,这题时间卡的太紧了,组合数要用阶乘+模逆元算,阶乘得预处理,此代码目前是这题得最快速度


#include <cstdio>
#define ll long long
int const MAX = 1e6 + 2;
int const MOD = 1e9 + 7;
ll fac[MAX];
int n, a, b;

void pre()
{
    fac[0] = fac[1] = 1;
    for(int i = 2; i <= MAX; i++)
        fac[i] = (fac[i - 1] * i) % MOD;
}

bool judge(int x)
{
    while(x)
    {
        if(x % 10 != a && x % 10 != b)
            return false;
        x /= 10;
    }
    return true;
}

ll inv(ll x)
{   
    ll res = 1, y = MOD - 2;
    while(y)
    {
        if(y & 1)
            res = (res * x) % MOD;
        x = (x * x) % MOD;
        y >>= 1;
    }
    return res;
}

ll C(int n, int m)
{
    return fac[n] * inv(fac[m]) % MOD * inv(fac[n - m]) % MOD;
}

int main()
{
    pre();
    while(scanf("%d %d %d", &a, &b, &n) != EOF)
    {
        int ans = 0;
        for(int i = 0; i <= n; i++) 
        {
            int sum = a * i + b * (n - i);
            if((sum % 10 != a) && (sum % 10 != b))
                continue;
            else if(judge(sum / 10))
                ans = (ans % MOD + C(n, i) % MOD) % MOD;
        }
        printf("%d\n", ans);
    }
}





自动售货机
时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 56            测试通过 : 12


题目描述
教学楼有一台奇怪的自动售货机,它只售卖一种饮料,单价5元,并且只收5元、10元面值的货币,但是同学们都很喜欢喝。这个售货机里没有多余的找零,也就是说如果一个持有10元的同学第一个购买,则他不能获得5元找零,但是如果在他之前有一个持有5元的同学买了这种饮料,则他可以获得5元找零。
假设售货机的货源无限,每人只买一罐,现在有N个持有5元的同学和M个持有10元的同学想要购买,问一共有多少种排队方法可以让每个持有10元的同学都获得找零。(这里的排队方法以某一位置上人持的钱数来分,即只要同一位置上的同学所持钱的数目相同,就算同一种排队方法)

输入
多组测试数据
每组包含两个整数N,M(1<=M<=N<=1000),分别表示持有5元和10元的同学个数。

输出
输出一个整数,表示排队方法总数。由于结果可能很大,所以结果需要模1000000007。

样例输入
1 1
2 1
3 1

样例输出
1
2
3

题目来源
hjp


题目分析:这题其实很简单,开始想的太复杂了,开始当作卡特兰数 (Catalan数)做其实就是(C(n+m, m)%mod - C(n+m, m-1)%mod)%mod,数组递推组合数T了 ,用java写大数结果noj上mle,连乘组合数取余写跪了,下面说这题应该怎么做。

其实就是一个dp,dp[i][j]表示有i个人有5元,j个人有10元的排队方案数,我们可以发现:

dp[i][0] = 1,因为大家都只有5元,怎么排都是一种方案

i < j时dp[i][j] = 0,因为有5元的人比有10元的少,必然会出现找不开的情况,那么此时方案数就是0

不是以上两种情况时:dp[i][j]的方案数由dp[i - 1][j] + dp[i][j - 1]递推得到,考虑第m+n个人的状态

1.第m+n个人100,m+n-1里有m个50,n-1个100则dp[m][n-1]
2.第m+n个人50,m+n-1里有m-1个50,n个100则dp[m-1][n]


#include <cstdio>
#include <cstring>
int dp[1005][1005];
int const MOD = 1e9 + 7;

int main()
{
    memset(dp, 0, sizeof(dp));
    for(int i = 0; i <= 1000; i++)
        dp[i][0] = 1;
    for(int i = 1; i <= 1000; i++)
        for(int j = 1; j <= i; j++)
            dp[i][j] = ((dp[i][j - 1] % MOD) + (dp[i - 1][j] % MOD)) % MOD;
    int n, m;
    while(scanf("%d %d", &m, &n) != EOF)
        printf("%d\n", dp[m][n] % MOD);
}




Prime

时间限制(普通/Java):1000MS/3000MS         运行内存限制:65536KByte
总提交:267          测试通过:11

比赛描述
给定n个数,求两两互斥的对数。互斥是指两个数的最大公约数是1

输入
第一行为样例数T(T<=5)
对每个样例,第一行为一个整数n(2=<n<=10^5),代表数的个数。
接下来一行包含n个数,a1,a2,…,an(1<=ai<=10^5)

输出
对于每个样例,在一行输出答案。

样例输入
1
2
2 3

样例输出
1


题目分析:kss出的题orz,看了css的题解后来才发现其实就是裸的莫比乌斯反演,先预处理处1e5的莫比乌斯函数
因为mob[i]=1表示i是偶数个素因子的乘积,mob[i]=-1表示i是奇数个素因子的乘积,mob[i]=0表示其他
回到这道题上,首先对于总的集合我任意取出两个数的情况数为C(n,2)即  n * (n - 1) / 2,然后依次减去不满足的情况,即gcd为2的gcd为3的,这里就出问题了,因为如果gcd为6,那就被减了两次,所以要容斥一下,即拿总的情况-gcd只由一个素因子构成的情况+gcd只有两个素因子构成的情况。。。对于每个gcd值的集合我们可以用一个num数组记录。然后就可以看出莫比乌斯函数的强大了,容斥时对应的正负号其实就是mob数组,比如计算gcd为2的集合时,mob[2]==-1,因此减去 num[2] * (num[2] - 1) / 2,3的时候也是减,6的时候则是加,正好与mob函数的定义吻合


#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
int const MAX = 1e5 + 5;
int p[MAX], cnt[MAX], num[MAX], mob[MAX];
bool prime[MAX];
int pnum, ma, n;

void Mobius()   //求解莫比乌斯函数
{
    pnum = 0;
    mob[1] = 1;
    memset(prime, true, sizeof(prime));
    for(int i = 2; i < MAX; i++)
    {
        if(prime[i])
        {
            p[pnum ++] = i;
            mob[i] = -1;
        }
        for(int j = 0; j < pnum && i * p[j] < MAX; j++)
        {
            prime[i * p[j]] = false;
            if(i % p[j] == 0)
            {
                mob[i * p[j]] = 0;
                break;
            }
            mob[i * p[j]] = -mob[i];
        }
    }
}

ll cal()
{
    ll ans = (ll) n * (n - 1) / 2;
    for(int i = 2; i <= ma ; i++)
    {
        num[i] = 0;
        for(int j = i; j <= ma; j += i)
            num[i] += cnt[j];   //得到gcd为i的集合的元素个数
    }   
    for(int i = 2; i <= ma; i++)
        ans += (ll) mob[i] * num[i] * (num[i] - 1) / 2;
    return ans;
}

int main()
{   
    Mobius();
    int T;
    scanf("%d", &T);
    while(T--)
    {
        memset(cnt, 0, sizeof(cnt));
        ma = 0;
        scanf("%d", &n);
        for(int i = 0; i < n; i ++)
        {
            int tmp;
            scanf("%d", &tmp);
            cnt[tmp] ++;
            ma = max(ma, tmp);
        }
        printf("%I64d\n", cal());
    }
}




 KSS的金牌梦1
时间限制(普通/Java) : 3000 MS/ 9000 MS          运行内存限制 : 65536 KByte
总提交 : 56            测试通过 : 7

题目描述
KSS是nupt集训队里公认的最具有金牌实力的选手,熟练掌握多种金牌算法,但是由于队友水平太菜和自身情绪不稳定,一直没能拿到金牌。KSS为了圆梦,想为自己制定一个训练计划,那么问题来了:
ACM中有许多算法之间是有单方面依赖关系的,比如:想学会A,就必须先学B,由于KSS很聪明,所以它可以学完A再学B;当然也存在两种或多种算法相互交融的情况,比如:想学会A,就必须先学B,想学会B,就必须先学A,这种情况KSS就不知从何下手了。
现在给出KSS打算学习的一些算法之间的依赖关系,KSS将尽自己最大的努力去学习这些算法。再给出比赛会出现的算法,如果KSS能学会超过70%的比赛算法,他就能圆梦,否则,他只能含恨退役。

输入
多组测试用例。
第一行一个整数N(0<=N<=250000)表示有N对算法间存在依赖关系,保证涉及的算法总数不超过500
接下来N行每行有两个字符串(以空格分割),表示前一个算法依赖后一个算法,第N+1行有一个整数M(0<M<=1000)表示比赛会出现M个算法,接下来M行每行有一个字符串表示比赛出现的算法。(字符串保证不含空格)

输出
如果KSS可以圆梦,输出“Excelsior!”,否则,输出“KSS have a dream!”。(不用输出引号)

样例输入
4
Aho-Corasickautomaton KMP
Aho-Corasickautomaton trietree
Inclusion-ExclusionPrinciple Mobiusinversion
Mobiusinversion Inclusion-ExclusionPrinciple
5
KMP
trietree
Aho-Corasickautomaton
Splay
Suffixarray

样例输出
KSS have a dream!

提示
对于样例,KSS可以学会KMP、trietree、Aho-Corasickautomaton,但是并不能学会Inclusion-ExclusionPrinciple、Mobiusinversion,所以只能掌握60%的比赛算法

题目来源
hjp



题目分析:最伤心的一题。。。其实并不难可是全场就2人过还是在最后时候,所以并没有开它而是选择一直被数论坑着,赛后一下就补出来了。

这题就是裸的拓扑排序,出题人比较良心,没有卡map和cin的时间,不然字符串hash写就麻烦了,所以直接map存一下,建个图,拓扑排个序最后判断一下就行了,吐槽一下,我还是相信kss可以拿到金牌的

简单说下拓扑排序,就是用栈维护一个入读为0的点集,每次删点(出栈)然后修改图上各剩余点的入度,再将入度为0的点入栈,一直到栈为空,即不存在入度为0的点为止


#include <cstdio>
#include <cstring>
#include <stack>
#include <map>
#include <string>
#include <iostream>
using namespace std;
map <string, int> mp;
map <string, int> :: iterator it;
int const MAX = 505;
int m, n, cnt;
int g[MAX][MAX], ind[MAX], tmp[MAX];
int re[MAX];
string s1, s2;

int TopoSort()
{
    bool flag = false;
    int len = 0;
    memcpy(tmp, ind, sizeof(ind));
    stack <int> s;
    for(int i = 0; i < cnt; i++)
        if(!tmp[i])
            s.push(i);
    while(!s.empty())
    {
        int pos = s.top();
        s.pop();
        re[pos] ++;
        len ++;
        for(int i = 0; i < cnt; i++)
            if(g[pos][i] && --tmp[i] == 0)
                s.push(i);
    }
    return len;
}

int main()
{
    while(scanf("%d", &m) != EOF)
    {
        mp.clear();
        cnt = 0;
        memset(g, 0, sizeof(g));
        memset(ind, 0, sizeof(ind));
        memset(re, 0, sizeof(re));
        while(m --)
        {
            cin >> s1 >> s2;
            it = mp.find(s1);
            if(it == mp.end())
                mp[s1] = cnt++;
            it = mp.find(s2);
            if(it == mp.end())
                mp[s2] = cnt++;
            g[mp[s2]][mp[s1]] = 1;
            ind[mp[s1]]++;
        }
        int ans = TopoSort();
        bool flag = false;
        scanf("%d", &n);
        while(n --)
        {
            cin >> s1;
            it = mp.find(s1);
            if(it == mp.end())  //如果这个算法没出现过,kss肯定就跪键盘了
            {
                flag = true;
                continue;
            }
            if(!re[mp[s1]])   //如果这个算法出现过,可是kss没学会。。可怜的kss
            {
                flag = true;
                continue;
            }
        }
        if(flag)
            printf("KSS have a dream!\n");
        else
            printf("Excelsior!\n");
    }
}



 Football
时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 254            测试通过 : 64

题目描述
现在你是一名足球经理,你的队伍将参加“南邮杯”的比赛。然而你拥有预知未来的能力,你可以预见你的队伍接下来进行的n场比赛每场的进球数和失球数。每胜一场队伍可得3分,平一场可得1分,输一场得0分。然而“南邮杯”是有黑幕的,你通过砸钱现在可以买到m个进球,问现在如何安排这m个进球,可以使得队伍获得最大的积分,求出这个最大的积分。

输入
多样例输入。
第一行给出n(1<=n<=10)和m(0<=m<=20)分别代表你队伍进行的比赛数以及队伍可买的进球数。
接下来n行,每行分别有两个数x和y分别表示该场比赛在没有买进球的情况下你队伍的进球数和失球数。

输出
对于每个样例答案输出一行输出一个整数,表示通过买球的方式你的队伍可获得的最大积分。

样例输入
2 1
1 1
1 1
3 2
1 3
3 1
2 2
4 10
1 1
2 2
1 3
0 4

样例输出
4
6
12

题目分析:签到题,按差值(x - y)从大到小排序贪心,差值大于0的不用处理,小于等于0的模拟一下

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n, m;

struct Data
{
    int x, y;
    int val;
}d[100];

bool cmp(Data a, Data b)
{
    return a.val > b.val;
}

int main()
{
    while(scanf("%d %d", &n, &m) != EOF)
    {
        for(int i = 0; i < n; i++)
        {
            scanf("%d %d", &d[i].x, &d[i].y);
            d[i].val = d[i].x - d[i].y;
        }
        sort(d, d + n, cmp);
        for(int i = 0; i < n; i++)
        {
            if(d[i].val > 0)
                continue;
            else 
            {
                while(d[i].val <= 0 && m > 0)
                {
                    m --;
                    d[i].val ++;
                }
            }
            if(m == 0)
                break;
        }
        int ans = 0;
        for(int i = 0; i < n; i++)
        {
            if(d[i].val > 0)
                ans += 3;
            if(d[i].val == 0)
                ans += 1;
        }
        printf("%d\n", ans);
    }
}


    
法师

时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 172            测试通过 : 28


题目描述
说到法师,也许大家第一反应便是脆弱的身躯与强大的爆发能力。诚然如此,在《炉石传说》中,法师拥有着最高伤害的单体法术——炎爆术,同时还有同样高伤害的火球术。但法师并不仅限于此,如果说这两张火系法术代表着的是法师的爆发。那么冰系法术就代表了法师的控制,冰霜新星、冰锥术以及暴风雪和寒冰箭都能够使对手冻结。
每张卡牌能造成一定的伤害,同时也要花费一定的法力水晶。当法力水晶不够的时候,你便不能打出相应的卡牌。
为了简单起见,我们只考虑以下几张卡牌。
寒冰箭 :消耗2点法力水晶,对一个角色造成3点伤害,并使其冻结。
冰枪术:消耗1点法力水晶,使一个角色冻结,如果它已经被冻结,则改为对其造成4点伤害。
火球术:消耗4点法力水晶,造成6点伤害。
炎爆术:消耗10点法力水晶,造成10点伤害。
现在,告诉你现在拥有的法力水晶,以及手上拥有的这四种卡牌的数目(可能为0),问你能对敌方英雄造成多少点伤害。

输入
第一行为一个正整数T,表示有T组数据。
每组数据第一行有1个整数: n表示当前拥有的法力水晶个数0<=n<=10。
第二行为四个整数a,b,c,d分别表示拥有寒冰箭、冰枪术、火球术、炎爆术的数目。0<=a,b,c,d<=10.

输出
一个整数表示最大可能造成的伤害值。

样例输入
2
9
0 0 3 0
5
2 2 1 1

样例输出
12
11

作者:伟大的css


题目分析:css出题太良心了,看看数据范围,直接暴力搞一下,不过不知道有没有贪心或者dp解法


#include <cstdio>
#include <algorithm>
using namespace std;
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int a, b, c, d, n;
        scanf("%d", &n);
        scanf("%d %d %d %d", &a, &b, &c, &d);
        int ans = 0;
        
            for(int i = 0; i <= a; i++)
            {
                for(int j = 0; j <= b; j++)
                {
                    for(int k = 0; k <= c; k++)
                    {
                        for(int l = 0; l <= d; l++)
                        {
                            if(2 * i + 1 * j + 4 * k + 10 * l <= n)
                            {
                                if(i > 0) //用寒冰箭冰冻
                                    ans = max(ans, 3 * i + 4 * j + 6 * k + 10 * l);
                                else
                                {
                                    if(j >= 1) //用冰枪术冰冻
                                        ans = max(ans, 4 * (j - 1) + 6 * k + 10 * l);
                                    else
                                        ans = max(ans, 6 * k + 10 * l);
                                }    
                            }
                        }
                    }
                }
            }
        printf("%d\n", ans);
    }
}


 送花
时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 115            测试通过 : 40

题目描述
萌妹纸一般都比较喜欢漂亮的鲜花。每逢各种节日,她们都想收到鲜花作为礼物。如果你是有妹纸滴人,经常不送妹纸花的话,结果可想而知了。
当然咯,妹纸都是通情达理的,不会因为某几次你木有送花,就发你好人卡了。王童鞋作为一个比较节俭(抠门)的人便知道这一道理,因此他想在妹纸不给他发好人卡的前提下,送尽量少的花。
为了简单起见,我们定义一个妹纸的幸福指数H(初始为0 )。如果某天幸福指数H小于0,那就。。。
如果某天妹纸收到了花,幸福指数H会增加ai,如果没收到,会下降bi。不同的日子送花对幸福指数的增加可能会有所不同,比如在2月14号送花就会比2月15号效果好~
即告诉你总天数n(1<=n<=365),每天收到花幸福指数的增加值ai(1<=ai<=10),没收到花幸福指数的降低值bi,求为了让妹纸的幸福指数H一直>=0,王童鞋至少要送妹纸多少朵花。


输入
第一行为一个正整数T,表示有T组数据。
每组数据第一行有1个整数: n表示总天数1<=n<=365。
第二行为n个整数ai表示第i天收到花幸福指数的增加值,1<=ai<=10。第三行为n个整数bi表示第i天没收到花幸福指数的下降值,1<=bi<=10。

输出
一个整数表示最少需要送多少朵花。

样例输入
2
1
3
4
5
5 2 10 1 1
1 1 1 5 5

样例输出
1
2


作者:伟大的kss


题目分析:据说这题数据n最大是10,贪心可搞,不过还是dp搞的。

dp[i][j]表示前i天妹子幸福值为j的送花数


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int const MAX = 400;
int const INF = 0x3fffffff;
int dp[MAX][4000];
int a[MAX], b[MAX];

int main()
{
    int T, n;
    scanf("%d",&T);
    while(T--)
    {
        int ans = INF;
        int suma = 0;
        scanf("%d",&n);
        memset(dp, -1, sizeof(dp));
        dp[0][0] = 0;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
            suma += a[i];
        }
        for(int i = 1; i <= n; i++)
            scanf("%d",&b[i]);
        for(int i = 1; i <= n; i++)
        {
            for(int j = 0; j <= suma - a[i]; j++)
            {
                if(dp[i - 1][j] == -1)  //前一天的状态不存在
                    continue;
                if(dp[i][j + a[i]] == -1)   //当天状态不存在则由前一天推出来
                    dp[i][j + a[i]] = dp[i - 1][j] + 1;
                //当天状态存在则取最小,即判断前一天幸福值为j且当天送花得到的当天状态值
                //是不是比原来的小,是就更新
                else
                    dp[i][j + a[i]] = min(dp[i][j + a[i]], dp[i - 1][j] + 1);
            }
            //下面是不送花的情况,和上面类似
            for(int j = b[i]; j <= suma; j++)
            {
                if(dp[i - 1][j] == -1) 
                    continue;
                if(dp[i][j - b[i]] == -1)
                    dp[i][j - b[i]] = dp[i - 1][j];
                else
                    dp[i][j - b[i]] = min(dp[i][j - b[i]], dp[i - 1][j]);
            }
        }
        //取前n天妹子幸福值大于等于0时送花的最小值
        for(int j = 0; j <= suma; j++)
        {
            if(dp[n][j] == -1) 
                continue;
            ans = min(ans, dp[n][j]);
        }
        printf("%d\n", ans);
    }
}



百度之星程序设计题目 百度之星程序设计题目,百度之星程序设计题目 立即下载

相关推荐

stm32学习笔记-启动文件

1、配置栈 Stack_Size EQU 0x00000400 AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem SPACE Stack_Size __initial_sp EQU:相当于C中的define,定义Stack_Size = 0x00000400。 AREA: 指...

某风吾起的博客 4487

31万奖金池!第七届科技图算法大正式启动!

点击边框调出视频工具条关于也:科技是在美上市的金融科技集团,力图通过大数据、人工智能等先进技术实现“科技,让金融更美好”的使命,推动金融服务从可获得进一步向可负担、可任和可享受进化,最终成为最受用户欢迎,最受伙伴任的金融科技平台。科技旗下包括科技驱动的消费金融业务、国际业务、智能零售等板块,坚持以创新技术服务大众、赋能机构,助力实体经济发展。立足中国,也科...

阿木寺的博客 465

【回答问题】ChatGPT上线了!如何安装python-ipopt?python-ipopt有哪些用法?

python-ipopt是一种基于Python语言的求解非线性最优化问题的软件包。它使用了Interior Point Optimizer(IPOPT)算法来求解最优化问题。这段代码使用python-ipopt求解了一个无约束的非线性最小化问题,其目标函数为(x[0] - 1) ** 2 + (x[1] - 2) ** 2,求解结果为x_opt。求解线性规划问题、二次规划问题、二次范数最小化问题等类型的最优化问题。对于给定的最优化问题,可以设置不同的求解参数来控制求解的精度和效率。

源代码杀手的博客 2113

总奖金池高达31万元,第七届科技图算法大开始报名啦!

点击边框调出视频工具条关于也:科技是在美上市的金融科技集团,力图通过大数据、人工智能等先进技术实现“科技,让金融更美好”的使命,推动金融服务从可获得进一步向可负担、可任和可享受进化,最终成为最受用户欢迎,最受伙伴任的金融科技平台。科技旗下包括科技驱动的消费金融业务、国际业务、智能零售等板块,坚持以创新技术服务大众、赋能机构,助力实体经济发展。立足中国,也科...

Datawhale 427

@AI大神们 喜提31万奖金,科技等你来战!

六岁,可见证一个孩子从稚嫩期步入学龄期;六年,可陪伴也魔镜变身科技,漫漫岁月,也为技术发烧友们提供交流平台的初心至此如一!2021年,第六届科技霸气归来,即日起即可报名,...

gzq0723的博客 268

2021-11-10

输入 输入数据有多组,第一行是一个正整数t,表示有t组测试数据,每组测试数据输入占一行,包括两个整数m和n(100<=m<=n<=999)。 输出 对于每组测试数据,要求输出所有在给定范围内的水仙花数,就是说,输出的水仙花数必须大于等于m,并且小于等于n,如果有多个,则要求从小到大排列在一行内输出,之间用一个空格隔开; 如果给定的范围内不存在水仙花数,则输出no;每组测试数据的输出占一行。 输入样列 2 100 120 300 380 输出样例 no 370 371 #include &l

m0_63992602的博客 2702

ZCMU--1134: 青蛙约会(C语言)

Description 两只青蛙在一个点,但是他们想要来个久别胜新婚的约会,于是他们出发,朝同一个方向绕圈跳,我们求出他们相遇的时间 Input 输入数据的第一行为一个正整数T, 表示测试数据的组数. 然后是T组测试数据. 每组测试数据包含两组正整数,用空格隔开。每组包含两个正整数,表示跳n圈需要的秒数(1/2,表示跳2圈要1秒),用'/'隔开。 Output 对于每组测试数据, 输出它们的下次相遇时间,如果相遇周期是整数则用整数表示,否则用最简分数表示。 Sample Input 2 1/

小小小Why的博客 2374

input&output II

输入数据的第一行为一个整数T,表示有T组数据。随后的T行中,每行有两个整数A和B。对每组输入,在单独的行中输出结果。计算两个32位整数A和B的和!

沐风—云端行者 182

输入第一行是一个整数T,表示有T组测试实例; 每组输入包括两行: 第一行一个数n表示接下来会有n个整数; 第二行空格隔开的n个数。 输出 对于每组输入,在一行输出n个数的和

#include<stdio.h> int main() { /*求n个整数的和。 输入 输入第一行是一个整数T,表示有T组测试实例; 每组输入包括两行: 第一行一个数n表示接下来会有n个整数; 第二行空格隔开的n个数。 输出 对于每组输入,在一行输出n个数的和(保证和不会超出int类型的范围)! 样例输入 Copy 2 3 1 2 3 4 -1 0 -19 22 样例输出 Copy ...

qq_43728862的博客 8万+

预处理01背包

输入 输入第一行包含三个正整数n,m,t,代表商店物品的数量,鸡尾酒带的钱,和询问的次数。(n,m<=2000,t<=3000) 接下来n行,每行输入两个正整数,分别代表第i个物品在平常的价格ai和价值bi。(ai<=m, bi<=1e9) 接下来有t组询问,每组询问包含三个数字,x,c,d。代表某一天第x个物品参与“特别活动”,并且价格变为c,价值变为d。(c<=...

qq_40423146的博客 265

计算两个日期之间的日期差。输入:第一行为一个整数T,表示有T组数据,每行三个整数year, month, day 分别代表年,月,日。输出:每组输出一个整数,表示从2012年3月12到给出的日期共几天

# 输入:第一行为一个整数T,表示有T组数据,接下去T行,每行三个整数year, month, day 分别代表年,月,日。 # 输出:对于每组数据输出1个整数,表示从2012年3月12日到给出的日期经过了多少天。 # 起始时间为:2012年3月12日。 month_day = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] # 润年2...

CSDN_persist的博客 4777

2020年百度之星程序设计-初一(Drink、GPA、Dec)

结果如何呢?充满感慨~ 参加这个比,发现确实要成功accept有点难度,算是见识到了,还是ACM大佬厉害。 小白直接上题目了。 Drink Problem Description 我们有 n 种不同的饮料,每种饮料有无限多瓶,第 ii种饮料一瓶提供 x[i] 毫升的水分,包含 y[i] 卡路里。 现在我们需要选择一种饮料一直喝,直到补充了至少 mm 毫升的水分,我们想使得摄入的卡路里总和最小。请求出这个最小值。 一旦打开一瓶饮料,就一定要喝完。 Input 第一行一个整数 test(1≤test≤10

陆海潘江的博客 4291

编程之美2015初第一场 题解

【A题】 彩色的树 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定一棵n个节点的树,节点编号为1, 2, …, n。树中有n - 1条边,任意两个节点间恰好有一条路径。这是一棵彩色的树,每个节点恰好可以染一种颜色。初始时,所有节点的颜色都为0。现在需要实现两种操作: 1. 改变节点x的颜色为y;

阿蒋的专栏 3327

c

Drink  Accepts: 1896  Submissions: 4596  Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: 32768/32768 K (Java/Others) Problem Description 我们有 nnn 种不同的饮料,每种饮料有无限多瓶,第 iii 种饮料一瓶提供 x[i]x[i]x[i] 毫升的水分,包含 y[i]y[i]y[i] 卡路里。 现在我们需要选择一种饮料一直喝,直到补充了至少 mmm 毫升

RUBGH的博客 372

“Wishare第八届大学生程序设计竞赛之现场决 题解报告

“Wishare第八届大学生程序设计竞赛网络预赛 题解报告

Tc的专栏 6832

迷宫问题

/*n行m列的迷宫,每个单元格要么是空地要么是障碍物,任务是帮助找到一条从迷宫的起点到小红的位置的最短路径,注意 障碍物是不能走的,也不能走到迷宫之外。 0表示空地,1标注障碍物 */ #include using namespace std; int n,m,p,q,mins=999999; int a[51][51],book[51][51]; int next[4][2]={{0,1},/

acm_JL的博客 1928

2019年暑期-第二期模拟题

第一题 危险的实验(dangerous) 【题意分析】 小明最近在上化学课,他需要使用到n种化学物质来进行他的实验。在做实验的时候,他需要将所有化学物质放在桌面上,按次序排成一条直线。然而每一种化学物质都是危险品,对于第i个化学物质,如果有另外一个化学物质距离它的距离小于ai,那么就会发生爆炸。小明想知道如果要安全的完成他的实验,桌子最短可以多短。 将n个化学物质放在桌子上,给出它...

weixin_30530523的博客 767

2020 年百度之星·程序设计 - 初一 Drink

Problem Description 我们有 nn 种不同的饮料,每种饮料有无限多瓶,第 ii 种饮料一瓶提供 x[i]x[i] 毫升的水分,包含 y[i]y[i] 卡路里。 现在我们需要选择一种饮料一直喝,直到补充了至少 mm 毫升的水分,我们想使得摄入的卡路里总和最小。请求出这个最小值。 一旦打开一瓶饮料,就一定要喝完。 Input 第一行一个整数 test(1 \le test \le 100)test(1≤test≤100) 表示数据组数。 对于每组数据,第一行两个整数 n, m(1 \le n

小哈里的博客 3217
上一篇: NOJ 2033 一页书的书 (组合数+dp)
下一篇: POJ 2431 Expedition (STL 优先权队列)
_TCgogogo_
博客等级 码龄12年 615粉丝 1081原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值