Codeforces Round #326 (Div. 2)总结

本文解析了三道算法竞赛题目,包括最小花费问题、最大孤独数问题及权重举重问题,详细阐述了解题思路与代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A题:

A题题目链接

题目描述:

A. Duff and Meat
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Duff is addicted to meat! Malek wants to keep her happy for n days. In order to be happy in i-th day, she needs to eat exactly aikilograms of meat.

There is a big shop uptown and Malek wants to buy meat for her from there. In i-th day, they sell meat for pi dollars per kilogram. Malek knows all numbers a1, ..., an and p1, ..., pn. In each day, he can buy arbitrary amount of meat, also he can keep some meat he has for the future.

Malek is a little tired from cooking meat, so he asked for your help. Help him to minimize the total money he spends to keep Duff happy for n days.

Input

The first line of input contains integer n (1 ≤ n ≤ 105), the number of days.

In the next n lines, i-th line contains two integers ai and pi (1 ≤ ai, pi ≤ 100), the amount of meat Duff needs and the cost of meat in that day.

Output

Print the minimum money needed to keep Duff happy for n days, in one line.

Sample test(s)
input
3
1 3
2 2
3 1
output
10
input
3
1 3
2 1
3 2
output
8
Note

In the first sample case: An optimal way would be to buy 1 kg on the first day, 2 kg on the second day and 3 kg on the third day.

In the second sample case: An optimal way would be to buy 1 kg on the first day and 5 kg (needed meat for the second and third day) on the second day.

题意:

Duff每天需要吃aikg的肉才开心(1<=i<=n),而每天肉的价钱是pi/kg(1<=i<=n),每天,Malek可以买好当日需要的肉的数量或者是把后来的天数需要的肉也买好。然后题目输入的第一行是一个整型数据n,表示天数,接下来有n行,每行有两个数,分别代表Duff当日需要肉的数量以及当日肉的单价。题目要求输出的是在这n天里,Malek花费最少的钱使得Duff这n天都开心(即每天买的肉至少是当日所需aikg)。

解析:

由于每天的单价都不一定相同,有高也有低,为了使花费的钱的总数最少,那么理所当然我们在价格低的时候购买足够多的肉使得这n天的总花费最低。比如说我们对于第二组数据:

3
1 3
2 1
3 2
在第一天的时候,肉的单价是3,比第二天高,所以呢,为了省钱,我们肯定不在第一天买好第二天需要的肉,这样的话第一天只买好当天需要的肉的数量,此时花费ans = 3;然后到了第二天,肉的单价变成了1,比第三天的单价低,所以呢,我们在第二天就买好了第三天所需要的肉,这样的话,在第三天就不需要再买肉了,这样的话还能省钱。所以呢,到了第二天,总花费变成ans += 5,即此时ans变为8,第三天不需要买任何肉,所以总最低花费就是8了。

有了以上思路,我们很快可以想到,可以利用每天的肉的单价设置一个基准值,只要哪天的价格比我这个基准值小的话,那么基准值被这个更低的价格代替,因为在这样的情况下,我们在以后的天数里才能更低价的买到肉(为了花费最少),一开始的话,我们为了方便,肯定用第一天的肉的单价作为基准值,然后先买好第一天的肉,再将基准与第二天的肉的单价相比较,如果发现第二天的肉的单价比基准低,那么此时基准值更新,否则的话,我们第一天就买好第二天的肉,然后继续将基准值与第三天的肉的单价比较,以此类推,直到第n天结束,得到总花费。

完整代码实现:

#include<cstdio>
#include<algorithm>
using namespace std;
typedef struct node Node;
typedef long long ll;
const int maxn = 1e5;
struct node
{
    int amount;
    int price;
};
Node tmp[maxn + 10];
int main()
{
    int n;
    while(scanf("%d",&n) == 1 && n)
    {
        ll ans = 0;
        for(int i = 0;i < n;i++)
            scanf("%d %d",&tmp[i].amount,&tmp[i].price);
        int flag_price = tmp[0].price;
        for(int i = 0;i < n;i++)
        {
            if(tmp[i].price < flag_price)
            {
                flag_price = tmp[i].price;
                ans += tmp[i].amount * flag_price;
            }
            else
                ans += tmp[i].amount * flag_price;
        }
        printf("%I64d\n",ans);

    }
    return 0;
}
B题:

B题题目链接
题目描述:

B. Duff in Love
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Duff is in love with lovely numbers! A positive integer x is called lovely if and only if there is no such positive integer a > 1 such that a2 is a divisor of x.

Malek has a number store! In his store, he has only divisors of positive integer n (and he has all of them). As a birthday present, Malek wants to give her a lovely number from his store. He wants this number to be as big as possible.

Malek always had issues in math, so he asked for your help. Please tell him what is the biggest lovely number in his store.

Input

The first and only line of input contains one integer, n (1 ≤ n ≤ 1012).

Output

Print the answer in one line.

Sample test(s)
input
10
output
10
input
12
output
6
Note

In first sample case, there are numbers 1, 2, 5 and 10 in the shop. 10 isn't divisible by any perfect square, so 10 is lovely.

In second sample case, there are numbers 1, 2, 3, 4, 6 and 12 in the shop. 12 is divisible by 4 = 22, so 12 is not lovely, while 6 is indeedlovely.

题意:

这道题是一道数学题,题目意思是给定你一个整数n,对于所有的n的因子(n%i==0)i1,i2,i3....in中,输出最大的并且需要满足条件不存在a^2的因子(a>1)。

解析:

由于任何合数都能够写成若干个质数之积,而质数等于其本身,所以我们从题目需要满足的条件出发,既然要输出最大的并且需要满足条件不存在a^2的因子(a>1),那我们很容易想到只要得到给定的数的所有质因子,然后重复的质因子只相乘一遍,那样的话就能得到满足条件的最大的数了,这样的话,我们就可以用循环解决。

或者我们还有一种思路,那就是不断寻找给定数的成对的质因子,然后将给定数除以该质因子,并且用sum记录该质因子(sum与该质因子相乘),直到给定数无成对的质因子,则最后用给定数除以所有重复的质因子之积(sum)即可得到最大的lonely数。

思路1:完整代码:

      //另解,分解质因子,只需将数n所有的质因子相乘即可
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
int main()
{
    ll n;
    while(scanf("%I64d",&n) == 1)
    {
        ll sum = 1;
        for(int i = 2;i <= sqrt(n);i++)
        {
            if(n % i == 0)
                sum *= i;
            while(n%i==0)
                n = n / i;
        }
        printf("%I64d\n",sum * n);
    }
    return 0;
}
思路2:完整代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
typedef long long ll;
int main()
{
    ll n;
    while(scanf("%I64d",&n) == 1 && n)
    {
        ll sum = 1,flag = n;
        for(ll i = 2;i * i <= flag;i++)
        {
            if(flag % (i * i) == 0)
            {
                sum *= i;
                flag /= i;
                i--;
            }
        }
        ll ans = n / sum;
        printf("%I64d\n",ans);
    }
    return 0;
}
C题:

C题题目链接

题目描述:

C. Duff and Weight Lifting
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Recently, Duff has been practicing weight lifting. As a hard practice, Malek gave her a task. He gave her a sequence of weights. Weight of i-th of them is 2wi pounds. In each step, Duff can lift some of the remaining weights and throw them away. She does this until there's no more weight left. Malek asked her to minimize the number of steps.

Duff is a competitive programming fan. That's why in each step, she can only lift and throw away a sequence of weights 2a1, ..., 2ak if and only if there exists a non-negative integer x such that 2a1 + 2a2 + ... + 2ak = 2x, i. e. the sum of those numbers is a power of two.

Duff is a competitive programming fan, but not a programmer. That's why she asked for your help. Help her minimize the number of steps.

Input

The first line of input contains integer n (1 ≤ n ≤ 106), the number of weights.

The second line contains n integers w1, ..., wn separated by spaces (0 ≤ wi ≤ 106 for each 1 ≤ i ≤ n), the powers of two forming the weights values.

Output

Print the minimum number of steps in a single line.

Sample test(s)
input
5
1 1 2 3 3
output
2
input
4
0 1 2 3
output
4
Note

In the first sample case: One optimal way would be to throw away the first three in the first step and the rest in the second step. Also, it's not possible to do it in one step because their sum is not a power of two.

In the second sample case: The only optimal way is to throw away one weight in each step. It's not possible to do it in less than 4 steps because there's no subset of weights with more than one weight and sum equal to a power of two.

题意:

第一行给定一个整数n,1<=n<=10^6,然后在第二行是n个整型数据(w1,w2,w3...wn),每个整型数据都是2^i的指数,当这n个整型数据中的任意i个满足条件2^w1 + 2^w2 + 2^w3 + ... + 2^wi = 2 ^x(x为非负整数)时,则Duff能将这i个砝码一步举起并且放下,题目问Duff最少用多少步将所有的砝码举起并且放下?

解析:

其实这道题目并不难,但是有个很大的坑点,后面解析的时候会提到。

通过观察和计算我们可以知道

2^i + 2^i = 2^(i+1);  (i为非负整数)

所以呢,两个幂指数相同的数可以转换成幂指数+1的数,所以呢,我们就可以将所有成双的幂指数相同的数全部转换成高一阶的数字,以此类推,高一阶的重复以上行为,直到没有成双的幂指数相同的数。那么就是我们最少需要走的步数。举个例子:

对于第一组测试数据:

1 1 2 3 3

由于有2^1 + 2^1 = 2^2,然后我们就有两个2^2,则又有2^2 + 2^2 = 2^3,这时候剩下3个2^3,其中两个转换成2^4,则最终结果就是2^4和2^3这两步。而由于给定数据范围并不大,所以我们可以运用"桶的思想"来对最终剩下的结果计数并输出。

其实从以上分析我们可以了解到,这也是贪心思想的一种运用,尽可能的将更多的数相加在一起,这样的话细分出来的步数才会最少。

坑点(也是这道题的难点和易错点):一般来说我们运用桶排序都只会申请比数据范围大5或者10左右的空间,但是这道题却不一样,我们运用“桶的思想”的情况下,应该考虑到如果有10^6个数据,每个数据都是10^6,那么桶的空间就至少要多20+,而这道题却恰恰卡在了这里,以后检查bug的时候,一定要注意数组是否申请的偏小。或者在申请数组的时候,在内存允许的情况下,就把数组申请的稍微大一点,比如说要求10^6的数组,那么尾数就加上1000等方法解决

完整代码:

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
const int maxn = 1e6;
int w[maxn+30],flag[maxn+30];
int main()
{
    int n;
    while(scanf("%d",&n) == 1 && n)
    {
        memset(flag,0,sizeof(flag));
        int ans = 0;
        for(int i = 0;i < n;i++)
        {
            scanf("%d",&w[i]);
            flag[w[i]]++;
        }
        for(int i = 0;i < maxn+30;i++)
        {
            if((flag[i] / 2) >= 1)
            {
                flag[i+1] += flag[i] / 2;
                if(flag[i] % 2 == 0)
                    flag[i] = 0;
                else
                    flag[i] = 1;
            }
        }
        for(int i = 0;i < maxn+30;i++)
        {
            if(flag[i])     ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}
如有错误,还请指正,O(∩_∩)O谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值