CodeForces(990A——990C) 题解

1——————————CodeForces 990A

Description

Berland Football Cup starts really soon! Commentators from all over the world come to the event.

Organizers have already built nn commentary boxes. mm regional delegations will come to the Cup. Every delegation should get the same number of the commentary boxes. If any box is left unoccupied then the delegations will be upset. So each box should be occupied by exactly one delegation.

If nn is not divisible by mm, it is impossible to distribute the boxes to the delegations at the moment.

Organizers can build a new commentary box paying aa burles and demolish a commentary box paying bb burles. They can both build and demolish boxes arbitrary number of times (each time paying a corresponding fee). It is allowed to demolish all the existing boxes.

What is the minimal amount of burles organizers should pay to satisfy all the delegations (i.e. to make the number of the boxes be divisible by mm)?

Input

The only line contains four integer numbers nn, mm, aa and bb (1≤n,m≤10121≤n,m≤1012, 1≤a,b≤1001≤a,b≤100), where nn is the initial number of the commentary boxes, mm is the number of delegations to come, aa is the fee to build a box and bb is the fee to demolish a box.

Output

Output the minimal amount of burles organizers should pay to satisfy all the delegations (i.e. to make the number of the boxes be divisible by mm). It is allowed that the final number of the boxes is equal to 00.

Sample Input

Input

9 7 3 8

Output

15

Input

2 7 3 7

Output

14

Input

30 6 17 19

Output

0

Hint

In the first example organizers can build 55 boxes to make the total of 1414 paying 33 burles for the each of them.

In the second example organizers can demolish 22 boxes to make the total of 00 paying 77 burles for the each of them.

In the third example organizers are already able to distribute all the boxes equally among the delegations, each one get 55 boxes.

题意:

给出n,m,a,b  ,表示有n个休息室,m个代表团,每个代表团必须有同样的休息室

如果m不能被n整除的话,你可以选择拆除,或新建一些休息室,

其中需要新建花费 a,拆除花费 b,求最少的花费

思路:

比较第一个比 m 小的 m的倍数 (代表要拆除的)和 第一个比n大的 m 倍数 (代表要新建的)的花费即可

n 与 m 相比 (在 n% m !=0 的前提下)

第一个比m 小的 m 倍数是:(n / m)* m

第一个比n  大的 m 倍数是:(n / m + 1)*  m

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<set>
#include <map>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
#define LL long long
#define INF 0x3f3f3f3f
#define MAX 300000+10
#define memset(a,n) memset(a,n,sizeof(a))
map<LL,LL>m;

int main()
{
    LL n,m,a,b;
    scanf("%lld %lld %lld %lld",&n,&m,&a,&b);
    if(n%m==0)
        printf("0\n");
    else{
        LL x=n/m;
        LL y=(n/m)+1;
        printf("%lld\n",min((y*m-n)*a,(n-m*x)*b));
    }
}

我的思路有点麻烦:

首先我分类讨论的:

在 n % m !=0的前提下:

1、如果 n < m 的话,可以选择拆除全部的 n ,也可以选择 建造 (m - n )个房间

2、如果 n > m 的话,可以选择拆除多余的房间,可以选择多建造几个 变成m 的倍数,当然也可以选择拆除全部的

                                             最后一种一开始忘记考虑,就wa 了一次

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<stack>
#include<map>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
#define swap(a,b) a=a+b,b=a-b,a=a-b
int  main()
{
    LL n,m,a,b;
    scanf("%lld  %lld %lld %lld",&n,&m,&a,&b);
    if(n%m==0)
        printf("0\n");
    else
    {
        LL ans=0,ans1=0,sum=0;
        if(n<m)
        {
            ans=(m-n)*a;
            sum=n*b;
            printf("%lld\n",min(ans,sum));
        }
        else{
            ans=((n/m+1)*m-n)*a; 
            sum=(n-n/m*m)*b;
            ans1=n*b;
            printf("%lld\n",min(min(ans,sum),ans1));
        }
    }
}

2——————————CodeForces 990B

Description

You have a Petri dish with bacteria and you are preparing to dive into the harsh micro-world. But, unfortunately, you don't have any microscope nearby, so you can't watch them.

You know that you have nn bacteria in the Petri dish and size of the ii-th bacteria is aiai. Also you know intergalactic positive integer constant KK.

The ii-th bacteria can swallow the jj-th bacteria if and only if ai>ajai>aj and ai≤aj+Kai≤aj+K. The jj-th bacteria disappear, but the ii-th bacteria doesn't change its size. The bacteria can perform multiple swallows. On each swallow operation any bacteria ii can swallow any bacteria jj if ai>ajai>aj and ai≤aj+Kai≤aj+K. The swallow operations go one after another.

For example, the sequence of bacteria sizes a=[101,53,42,102,101,55,54]a=[101,53,42,102,101,55,54] and K=1K=1. The one of possible sequences of swallows is: [101,53,42,102,101−−−,55,54][101,53,42,102,101_,55,54] →→ [101,53−−,42,102,55,54][101,53_,42,102,55,54] →→ [101−−−,42,102,55,54][101_,42,102,55,54] →→ [42,102,55,54−−][42,102,55,54_] →→ [42,102,55][42,102,55]. In total there are 33 bacteria remained in the Petri dish.

Since you don't have a microscope, you can only guess, what the minimal possible number of bacteria can remain in your Petri dish when you finally will find any microscope.

Input

The first line contains two space separated positive integers nn and KK (1≤n≤2⋅1051≤n≤2⋅105, 1≤K≤1061≤K≤106) — number of bacteria and intergalactic constant KK.

The second line contains nn space separated integers a1,a2,…,ana1,a2,…,an (1≤ai≤1061≤ai≤106) — sizes of bacteria you have.

Output

Print the only integer — minimal possible number of bacteria can remain.

Sample Input

Input

7 1
101 53 42 102 101 55 54

Output

3

Input

6 5
20 15 10 15 20 25

Output

1

Input

7 1000000
1 1 1 1 1 1 1

Output

7

Hint

The first example is clarified in the problem statement.

In the second example an optimal possible sequence of swallows is: [20,15,10,15,20−−,25][20,15,10,15,20_,25] →→ [20,15,10,15−−,25][20,15,10,15_,25] →→ [20,15,10−−,25][20,15,10_,25] →→[20,15−−,25][20,15_,25] →→ [20−−,25][20_,25] →→ [25][25].

In the third example no bacteria can swallow any other bacteria.

题意:

有n个细菌,每个细菌的尺寸为 ai ,现在有常数k,如果细菌 i 的尺寸 ai 大于细菌 j 的尺寸 aj ,并且 ai<=aj+k ,那么细菌i就可以吃掉细菌 j,问最后可以剩于多少个细菌。

从小开始判断,如果从 大开始判断的话,这个大的可以吃更小的,就会少判

第一种思路:去重排序,前后比较一下就可以了

(有尺寸相同的情况,所以要去重,用 map 记录一下该尺寸的细菌的个数即可)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<stack>
#include<map>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
#define swap(a,b) a=a+b,b=a-b,a=a-b
const int maxx=2e5+10;
LL a[maxx];
map<LL,LL>m;
bool cmp(int a,int b)
{
    return a<b;
}
int main()
{
    LL n,k;
    LL cnt=0;
    scanf("%lld %lld",&n,&k);
    for(int i=0;i<n;i++){
        scanf("%lld",&a[i]);
        m[a[i]]++;
    }
    cnt=n;
    int len=unique(a,a+n)-a;
    for(int i=1;i<len;i++)
    {
        if(a[i]-a[i-1]<=k)
            cnt-=m[a[i-1]];
    }
    cout<<cnt<<endl;
}

第二种 :

用的 map 

map 会自动排序,按从小到大的顺序排序

map<LL,LL>m;

迭代器    map<LL,LL>::iterator it;

表示键——(* it ).first

表示值——(* it ).second

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<stack>
#include<map>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
#define swap(a,b) a=a+b,b=a-b,a=a-b
const int maxx=2e5+10;
LL a[maxx];
map<LL,LL>m;
int main()
{
    LL n,k;
    LL cnt=0;
    scanf("%lld %lld",&n,&k);
    for(int i=0;i<n;i++){
        scanf("%lld",&a[i]);
        m[a[i]]++;
    }
    cnt=n;
    map<LL,LL>::iterator it;  // 迭代器
    for(it=m.begin();it!=m.end();it++)
    {
        LL a,b,c;
        a=(*it).first;  // 当前 A键
        c=(*it).second;
        it++;
        if(it==m.end())
            break;
        b=(*it).first; // 下一个 B键,与当前 A键比较
        it--; // 别忘了减回来,从 当前 A 键开始比较
        if(b-a<=k)
            cnt-=c;
    }
    cout<<cnt<<endl;
}

3——————————CodeForces 990C  (模拟 或者 栈 )

Description

A bracket sequence is a string containing only characters "(" and ")".

A regular bracket sequence is a bracket sequence that can be transformed into a correct arithmetic expression by inserting characters "1" and "+" between the original characters of the sequence. For example, bracket sequences "()()", "(())" are regular (the resulting expressions are: "(1)+(1)", "((1+1)+1)"), and ")(" and "(" are not.

You are given nn bracket sequences s1,s2,…,sns1,s2,…,sn. Calculate the number of pairs i,j(1≤i,j≤n)i,j(1≤i,j≤n) such that the bracket sequence si+sjsi+sj is a regular bracket sequence. Operation ++ means concatenation i.e. "()(" + ")()" = "()()()".

If si+sjsi+sj and sj+sisj+si are regular bracket sequences and i≠ji≠j, then both pairs (i,j)(i,j) and (j,i)(j,i) must be counted in the answer. Also, if si+sisi+si is a regular bracket sequence, the pair (i,i)(i,i) must be counted in the answer.

Input

The first line contains one integer n(1≤n≤3⋅105)n(1≤n≤3⋅105) — the number of bracket sequences. The following nn lines contain bracket sequences — non-empty strings consisting only of characters "(" and ")". The sum of lengths of all bracket sequences does not exceed 3⋅1053⋅105.

Output

In the single line print a single integer — the number of pairs i,j(1≤i,j≤n)i,j(1≤i,j≤n) such that the bracket sequence si+sjsi+sj is a regular bracket sequence.

Sample Input

Input

3
)
()
(

Output

2

Input

2
()
()

Output

4

Hint

In the first example, suitable pairs are (3,1)(3,1) and (2,2)(2,2).

In the second example, any pair is suitable, namely (1,1),(1,2),(2,1),(2,2)(1,1),(1,2),(2,1),(2,2).

题意:

给你  n个只有  ’(‘, ’)’  的字符串,问有对   (i,j) (i,j)  使得 Si+Sj是一个合法的括号序列,i  可以等于 j


思路:

字符串形式有:

1,只有左括号,

2,只有右括号,

3,既有左括号,又有右括号,但左括号在右边,右括号在左边,如:)(  

4,既有左括号,又有右括号,但左括号在右边,右括号在左边,如:)(  ————不合法

 统计合法的串的个数 x ,对答案贡献为  x^2 

例如样例 2

2

()——1

()——2

对答案的贡献是  (1,1) 、()()  (1,2)、()()   (2,2) 、()() (2,2)、()()

对于不合法的串:

把已经匹配的左右括号删去,如果串中还有  左右括号  那就一定存在  ”)(“   这种情况,对答案没贡献

如果只有左  或者  右括号, 用数组  L[i]  记录左括号个数为 i   的个数,R[i]    数组记录右括号个数为  i  的个数,最后L[i]*R[i]为这种情况对答案的贡献

判断:

1、如果 是个左括号,因为 ) (   ( 这一种是不合法的),L++

2、如果不是左括号并且L 不为 0,说明 有左括号 与 该右括号匹配,就可以消掉一个左括号

3、如果都不满足 说明是个单独的右括号, 则 R++

如果  L==0&&R==0,则说明左右括号完全匹配

如果  L!=0&&R !=0,说明左右括号都存在但没有完全消掉,说明是  ) ( 

记录 为 i 的左右括号的 数目

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<set>
#include <map>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
#define LL long long
#define INF 0x3f3f3f3f
#define MAX 300000+10
#define memset(a,n) memset(a,n,sizeof(a))

LL L[MAX];
LL R[MAX];
LL ans=0;

void check(char s[])
{
    LL len;
    LL l=0,r=0;
    len=strlen(s);
    for(LL i=0;i<len;i++)
    {
        if(s[i]=='(')
            l++;
        else if(l)
            l--;
        else
            r++;
    }
    if(l&&r)        //  )( 这一种情况
        return ;
    if(!l&&!r)     //   左右括号完全匹配
        ans++;
    L[l]++,R[r]++;  //  只有左 或 右括号
}
int main()
{
    LL n;
    memset(L,0);
    memset(R,0);
    char s[MAX];
    scanf("%lld",&n);
    for(LL i=0;i<n;i++)
    {
        scanf("%s",s);
        check(s);
    }
    ans*=ans;          // 合法的贡献 平方 的值
    for(LL i=1;i<=3e5;i++)
        ans+=L[i]*R[i]; 
    printf("%lld\n",ans);
}

也可以用   栈 + map 来做

将字符入栈,

如果当前是 ‘)’,栈顶元素是 ‘(’,则 出栈,匹配成功,否则入栈

当栈空的时候,说明找到了 合法的完全匹配的字符,计数 sum ++

否则,判断左右括号各出现了几次,用 map 存下来

存左括号存的是正的,存右括号 存 负的

遇到不合法的直接 return 

查询的时候 :

找到 左括号出现了 m 次,则去找 右括号出现 -m 次的

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<set>
#include <map>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
#define LL long long
#define INF 0x3f3f3f3f
#define MAX 100000+10
//LL a[MAXX];

char s[300010];
map <LL, LL> m;
LL sum;

void check() {
    stack <char> q;
    int len = strlen(s), n1 = 0, n2 = 0;

    for (int i = 0; i < len; i++) {
        if (!q.empty()) {
            if (s[i] == ')' && q.top() == '(') { // 符合 (),出栈
                q.pop();
                continue;
            } else {
                q.push(s[i]); 
            }
        } else {
            q.push(s[i]);
        }
    }
    if (q.empty()) {
        sum++;
        return ;
    }
    while (!q.empty()) {
        if (q.top() == '(') n1++;
        else n2--;
        q.pop();
    }
    if (n1 == 0 && n2 != 0) m[n2]++;
    if (n2 == 0 && n1 != 0) m[n1]++;
    return ;
}

int main() {
    int n;

    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%s", s);
        check();
    }

    sum = sum * sum;
    map <LL, LL>::iterator it, it2;
    for (it = m.begin(); it != m.end(); it++) {
        int p1 = (*it).first;
        if (p1 > 0) {     // 是左括号,必须找 () 这种的
            it2 = m.find(-p1); // 找右括号
            if (it2 != m.end()) {
                sum += (*it).second * (*it2).second;
            }
        }
    }
    printf("%lld\n", sum);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/JKdd123456/article/details/81434566