牛客网暑期ACM多校训练营(第三场

A PACM Team

链接:https://www.nowcoder.com/acm/contest/141/A
来源:牛客网

题目描述

Eddy was a contestant participating in ACM ICPC contests. ACM is short for Algorithm, Coding, Math. Since in the ACM contest, the most important knowledge is about algorithm, followed by coding(implementation ability), then math. However, in the ACM ICPC World Finals 2018, Eddy failed to solve a physics equation, which pushed him away from a potential medal.

Since then on, Eddy found that physics is actually the most important thing in the contest. Thus, he wants to form a team to guide the following contestants to conquer the PACM contests(PACM is short for Physics, Algorithm, Coding, Math).

There are N candidate groups each composed of pi physics experts, ai algorithm experts, ci coding experts, mi math experts. For each group, Eddy can either invite all of them or none of them. If i-th team is invited, they will bring gi knowledge points which is calculated by Eddy's magic formula. Eddy believes that the higher the total knowledge points is, the better a team could place in a contest. But, Eddy doesn't want too many experts in the same area in the invited groups. Thus, the number of invited physics experts should not exceed P, and A for algorithm experts, C for coding experts, M for math experts.

Eddy is still busy in studying Physics. You come to help him to figure out which groups should be invited such that they doesn't exceed the constraint and will bring the most knowledge points in total.

输入描述:

The first line contains a positive integer N indicating the number of candidate groups.
Each of following N lines contains five space-separated integer pi, ai, ci, mi, gi indicating that i-th team consists of pi physics experts, ai algorithm experts, ci coding experts, mi math experts, and will bring gi knowledge points.
The last line contains four space-separated integer P, A, C, M indicating the maximum possible number of physics experts, algorithm experts, coding experts, and math experts, respectively.

 1 ≤ N ≤ 36
 0 ≤ pi,ai,ci,mi,gi ≤ 36
 0 ≤ P, A, C, M ≤ 36

输出描述:

The first line should contain a non-negative integer K indicating the number of invited groups.
The second line should contain K space-separated integer indicating the index of invited groups(groups are indexed from 0).

You can output index in any order as long as each index appears at most once. If there are multiple way to reach the most total knowledge points, you can output any one of them. If none of the groups will be invited, you could either output one line or output a blank line in the second line.

示例1

输入

复制

2
1 0 2 1 10
1 0 2 1 21
1 0 2 1

输出

复制

1
1

示例2

输入

复制

1
2 1 1 0 31
1 0 2 1

输出

复制

0

题意:有 n 组,每组有 4 个容量和 一个组价值,最后再给出 4 个总容量 a,b,c,d;问在不超过 a,b,c,d 容量的情况下的最大价                   值。

题解:当时比赛数据出了问题导致用贪心水过了,后来只过了 case通过率为42.86%;正解应该是 DP。

wa 代码:

#include<stdio.h>
#include<string.h>
#include<map>
#include<queue>
#include<algorithm>
using namespace std;
int n;
struct fun{
    int a,b,c,d,vel,id;
}f[100];
queue<int>qq;
 
bool cmp(fun x,fun y){
    if(x.vel!=y.vel)
        return x.vel>y.vel;
    else if(x.a!=y.a)
        return x.a<y.a;
    else if(x.b!=y.b)
        return x.b<y.b;
    else if(x.c!=y.c)
        return x.c<y.c;
    else
        return x.d<y.d;
}
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d %d %d %d %d",&f[i].a,&f[i].b,&f[i].c,&f[i].d,&f[i].vel);
        f[i].id=i;
    }
    sort(f,f+n,cmp);
    int a,b,c,d;
    scanf("%d %d %d %d",&a,&b,&c,&d);
    int ans=0;
    for(int i=0;i<n;i++){
        if(f[i].a<=a&&f[i].b<=b&&f[i].c<=c&&f[i].d<=d){
            a-=f[i].a;
            b-=f[i].b;
            c-=f[i].c;
            d-=f[i].d;
            ans++;
            qq.push(f[i].id);
        }
    }
    printf("%d\n",ans);
    while(!qq.empty()){
        printf("%d\n",qq.front());
        qq.pop();
    }
    return 0;
}

AC 代码:

#include<bits/stdc++.h>
using namespace std;
const int N=37;
pair<int,long long> f[N][N][N][N],ans;
int n,P,A,C,M;
int p[N],a[N],c[N],m[N],v[N];
int d[N];
int main(){
    ios::sync_with_stdio(false);
    cin>>n;
    for (int i=0;i<n;i++){
        cin>>p[i]>>a[i]>>c[i]>>m[i]>>v[i];
    }
    cin>>P>>A>>C>>M;
    for (int i=0;i<n;i++){
        long long u=(1ll<<i);
        for (int p1=P;p1>=p[i];p1--)
            for (int a1=A;a1>=a[i];a1--)
                for (int c1=C;c1>=c[i];c1--)
                    for (int m1=M;m1>=m[i];m1--)
                        f[p1][a1][c1][m1]=max(f[p1][a1][c1][m1],make_pair(f[p1-p[i]][a1-a[i]][c1-c[i]][m1-m[i]].first+v[i],f[p1-p[i]][a1-a[i]][c1-c[i]][m1-m[i]].second+u));
    }
    for (int p1=0;p1<=P;p1++)
        for (int a1=0;a1<=A;a1++)
            for (int c1=0;c1<=C;c1++)
                for (int m1=0;m1<=M;m1++)
                    ans=max(ans,f[p1][a1][c1][m1]);
    for (int i=0;i<n;i++)
        if (ans.second&(1ll<<i))d[++d[0]]=i;
    cout<<d[0]<<endl;
    for (int i=1;i<=d[0];i++)
        cout<<d[i]<<' ';
    return 0;
}
C Shuffle Cards

链接:https://www.nowcoder.com/acm/contest/141/C
来源:牛客网

题目描述

Eddy likes to play cards game since there are always lots of randomness in the game. For most of the cards game, the very first step in the game is shuffling the cards. And, mostly the randomness in the game is from this step. However, Eddy doubts that if the shuffling is not done well, the order of the cards is predictable!

To prove that, Eddy wants to shuffle cards and tries to predict the final order of the cards. Actually, Eddy knows only one way to shuffle cards that is taking some middle consecutive cards and put them on the top of rest. When shuffling cards, Eddy just keeps repeating this procedure. After several rounds, Eddy has lost the track of the order of cards and believes that the assumption he made is wrong. As Eddy's friend, you are watching him doing such foolish thing and easily memorizes all the moves he done. Now, you are going to tell Eddy the final order of cards as a magic to surprise him.

Eddy has showed you at first that the cards are number from 1 to N from top to bottom.

For example, there are 5 cards and Eddy has done 1 shuffling. He takes out 2-nd card from top to 4-th card from top(indexed from 1) and put them on the top of rest cards. Then, the final order of cards from top will be [2,3,4,1,5].

输入描述:

The first line contains two space-separated integer N, M indicating the number of cards and the number of shuffling Eddy has done.
Each of following M lines contains two space-separated integer pi, si indicating that Eddy takes pi-th card from top to (pi+si-1)-th card from top(indexed from 1) and put them on the top of rest cards.


1 ≤ N, M ≤ 105
1 ≤ pi ≤ N
1 ≤ si ≤ N-pi+1

输出描述:

Output one line contains N space-separated integers indicating the final order of the cards from top to bottom.

示例1

输入

复制

5 1
2 3

输出

复制

2 3 4 1 5

示例2

输入

复制

5 2
2 3
2 3

输出

复制

3 4 1 2 5

示例3

输入

复制

5 3
2 3
1 4
2 4

输出

复制

3 4 1 5 2

题意:给你一个1 - n 的数列,再给你 m 个区间,每次给出的 区间将移至 数列的最前端;

题解:splay 树(不会写),那了解一下 stl 中的 Rope大法(可持久化平衡树)-------------------->一个很神奇的容器。

#include<stdio.h>
#include<string.h>
#include<ext/rope>
#include<algorithm>
using namespace std;
using namespace __gnu_cxx;
 
rope<int>rop;
int main(){
    int n,m,l,r;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
        rop.push_back(i);
    while(m--){
        scanf("%d %d",&l,&r);
        l-=1;
        rop=rop.substr(l,r)+rop.substr(0,l)+rop.substr(l+r,n-l-r+1);
    }
    int c=0;
    for(int i=0;i<n;i++)
        printf(c++==0?"%d":" %d",rop[i]);
    printf("\n");
    return 0;
}
E Sort String

链接:https://www.nowcoder.com/acm/contest/141/E
来源:牛客网
 

Eddy likes to play with string which is a sequence of characters. One day, Eddy has played with a string S for a long time and wonders how could make it more enjoyable. Eddy comes up with following procedure:

1. For each i in [0,|S|-1], let Si be the substring of S starting from i-th character to the end followed by the substring of first i characters of S. Index of string starts from 0.
2. Group up all the Si. Si and Sj will be the same group if and only if Si=Sj.
3. For each group, let Lj be the list of index i in non-decreasing order of Si in this group.
4. Sort all the Lj by lexicographical order.

Eddy can't find any efficient way to compute the final result. As one of his best friend, you come to help him compute the answer!

输入描述:

Input contains only one line consisting of a string S.

1≤ |S|≤ 106
S only contains lowercase English letters(i.e. ).

输出描述:

First, output one line containing an integer K indicating the number of lists.
For each following K lines, output each list in lexicographical order.
For each list, output its length followed by the indexes in it separated by a single space.

示例1

输入

复制

abab

输出

复制

2
2 0 2
2 1 3

示例2

输入

复制

deadbeef

输出

复制

8
1 0
1 1
1 2
1 3
1 4
1 5
1 6
1 7

题意:不好懂;

解释一个样例: abab;

0>  abab;     1> baba;   2> abab;  3>  baba;

2      含义: 有两组相同的字符串

2     0     2     ||||         2  含义:这一组包含 2 个元素, (0   2)含义:0号字符串 与 2号字符串 相等;

2     1     3     ||||         2  含义:这一组包含 2 个元素, (1   3)含义:1号字符串 与 3号字符串 相等;

题解:利用字符串的 循环节 这一特性求解,abab 的循环节是 ab(长度为2),所以有两组;剩下的无难度。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char s[100005];
int nex[100005];

void get(){
	int i=0,j=-1;
	nex[0]=-1;
	int len=strlen(s);
	while(i<len){
		if(s[i]==s[j]||j==-1){
			i++;
			j++;
			nex[i]=j;
		}
		else
		 j=nex[j];
	}
}
int main(){
    scanf("%s",s);
    get();
    int len=strlen(s);
    int sum;
		if(nex[len]){
			 int h=len-nex[len];
		     int k=nex[len-1]%h+1;
    //  a   b   c   a   b   c   a   b   _
    //  -1  0   0   0   1   2   3   4   5
    //  len=8;
    //  nex[len]=5;
    //  h=3;
    //  k=4%3+1==2 < 3
    //  所以,循环节是 它本身
		     if(k>=h){
		     	sum=h;
			 }
			 else{
			 	sum=len;
			 }
		}
		else{
			sum=len;
		}
	printf("%d\n",sum);  //  组数
	for(int i=0;i<sum;i++){
        printf("%d",len/sum);  // 每组的元素个数
        int m=i;
        while(m<len){
            printf(" %d",m);
            m+=sum;
        }
        printf("\n");
	}

	return 0;
}
H Diff-prime Pairs

链接:https://www.nowcoder.com/acm/contest/141/H
来源:牛客网
 

题目描述

Eddy has solved lots of problem involving calculating the number of coprime pairs within some range. This problem can be solved with inclusion-exclusion method. Eddy has implemented it lots of times. Someday, when he encounters another coprime pairs problem, he comes up with diff-prime pairs problem. diff-prime pairs problem is that given N, you need to find the number of pairs (i, j), where and are both prime and i ,j ≤ N. gcd(i, j) is the greatest common divisor of i and j. Prime is an integer greater than 1 and has only 2 positive divisors.

Eddy tried to solve it with inclusion-exclusion method but failed. Please help Eddy to solve this problem.

Note that pair (i1, j1) and pair (i2, j2) are considered different if i1 ≠ i2 or j1 ≠ j2.

输入描述:

Input has only one line containing a positive integer N.

1 ≤ N ≤ 107

输出描述:

Output one line containing a non-negative integer indicating the number of diff-prime pairs (i,j) where i, j ≤ N

示例1

输入

复制

3

输出

复制

2

示例2

输入

复制

5

输出

复制

6

题意:给你一个 N,然后在 1  ---- N 中找出一对 (i,j),满足:gcd(i,j)为 i , j 的最大公约数,h1==i/gcd(i,j) ;; h2=j/gcd(i,j);; h1和               h2 必须是大于 1 的素数。问最多可以找出多少对?

题解:样例解释:

N== 3   可以从中挑出 2,3 和 3,2;

N== 5   可以从中挑出 2,3 和 3,2 ;     2,5 和 5,2 ;      3,5 和 5,3 ; 

N== 6   可以从中挑出 2,3 和 3,2 ;     2,5 和 5,2 ;      3,5 和 5,3 ;      4,6和 6,4;

从中我们可得到规律,只要 i 和 j 是素数 都是符合条件的,还有一种情况,4,6  和 9,15 和 8,12 这些 合数对也是,那么我们该怎                                           么计算他们的数量:

例如: N==6    有 素数 2 的个数 :N/2=3,分别是 2,4,6    ||     2 在素数列表中的位置是 0(下标从0开始)

                           有 素数 3 的个数 :N/3=2,分别是 3,6       ||     3 在素数列表中的位置是 1

                           有 素数 5 的个数 :N/5=1,分别是 5          ||      5 在素数列表中的位置是 2

#include<stdio.h>
#include<string.h>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
int a[10000005],b[10000005],p=0;
map<int,int>mapp;
void fun(){
    a[1]=1;  // 埃氏筛复杂度O(nloglogn)很接近O(n) 
    for(int i=2;i<=10000000;i++){
        if(!a[i]){
             mapp[i]=p;   // 记录每个素数所在素数列的位置
             p++;
             for(int j=i*2;j<=10000000;j+=i)
                a[j]=1;
        }
    }
}
int main(){
    int n;
    fun();
    scanf("%d",&n);
    memset(b,0,sizeof(b));
    for(int i=1;i<=n;i++){
        if(!a[i]){
            b[i]=n/i;   // 求出 每个素数在 1 ——— N 中的个数
        }
    }
    long long sum=0;
    for(int i=10000000;i>=3;i--){
        if(b[i]>0){
            sum+=(1ll*mapp[i]*b[i]);
        }
    }
    printf("%lld\n",sum*2);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/black_horse2018/article/details/81231997