2020牛客国庆DAY1

A.ABB:
链接:https://ac.nowcoder.com/acm/contest/7817/A
来源:牛客网

Fernando was hired by the University of Waterloo to finish a development project the university started some time ago. Outside the campus, the university wanted to build its representative bungalow street for important foreign visitors and collaborators.
Currently, the street is built only partially, it begins at the lake shore and continues into the forests, where it currently ends. Fernando’s task is to complete the street at its forest end by building more bungalows there. All existing bungalows stand on one side of the street and the new ones should be built on the same side. The bungalows are of various types and painted in various colors.
The whole disposition of the street looks a bit chaotic to Fernando. He is afraid that it will look even more chaotic when he adds new bungalows of his own design. To counterbalance the chaos of all bungalow shapes, he wants to add some order to the arrangement by choosing suitable colors for the new bungalows. When the project is finished, the whole sequence of bungalow colors will be symmetric, that is, the sequence of colors is the same when observed from either end of the street.
Among other questions, Fernando wonders what is the minimum number of new bungalows he needs to build and paint appropriately to complete the project while respecting his self-imposed bungalow color constraint.

题目大意:
在结尾添加多少个字符可以使得字符串成为一个回文字符串。

思路:
用马拉车的思想,对于字符串对称的形式: 一种是形如ABBA式, 对应标准串中以’#'为回文中心的形式. 而另一种是形如ABA式, 对应标准串中以’X’为回文中心的字符串.

我们通过观察会发现, 最理想的情况为该串本身即为回文串, 即对称中心在串长的一半处. 如果不是, 则补成回文串后, 对称中心会右移. 所以我们只需要依次枚举对称中心即可.

如果找到了对称中心, 我们可以发现无论是哪种对称形式, 所需要补充的字符数字都为下标/2.

代码:

#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <cmath>
#include <algorithm>
#include<bits/stdc++.h>
using namespace std;
const double N = 1e6+10;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
const inline int read(){
    int k = 0, f = 1; char c = getchar();
    for(;!isdigit(c); c = getchar())
        if(c == '-') f = -1;
    for(;isdigit(c); c = getchar())
        k = k * 10 + c - '0';
    return k * f;
}
#define ll long long
#define CL(a,b) memset(a,b,sizeof(a))
#define MAXN 1000010
vector<int> G[MAXN];
int n , x , y , res;
char s[MAXN];
char Ma[MAXN];
int Mp[MAXN];
int l;
void Manacher(char s[] , int len)
{
	l = 0;
	Ma[l++] = '$';
	Ma[l++] = '#';
	for(int i = 0 ; i < len ; i++)
	{
		Ma[l++] = s[i];
		Ma[l++] = '#';
	}
	Ma[l] = 0;
	int mx = 0;
	int id = 0;
	for(int i = 0 ; i < l ; i++)
	{
		Mp[i] = mx>i?min(Mp[2*id-i],mx-i):1;
		while(Ma[i+Mp[i]]==Ma[i-Mp[i]])
			Mp[i]++;
		if(i+Mp[i] > mx)
		{
			mx = i+Mp[i];
			id = i;
		}
	}
}
int main()
{
    scanf("%d",&n);
    scanf("%s",s);
    Manacher(s,n);
    int res = 0;
    for(int i = 2 ; i < l; i++)
    {
    	if(Mp[i]==1) continue;
		if((i-Mp[i])/2+Mp[i]-1==n)
		{
			res = (i-Mp[i])/2;
			break;
		}
	}
	printf("%d\n",res);
    return 0;
}

C.Bob in Wonderland
题目:
链接:https://ac.nowcoder.com/acm/contest/7817/C
来源:牛客网

A chain, as everybody knows, is made of connected links. Typically, all links are of the same shape and size. Bob is a blacksmith apprentice, and he is making his own first iridium chain. He follows the traditional formula of chain-making. It says:
If there is no chain yet, make a link and it will be a piece of your chain.
If there is a piece of chain, make another link and connect it to one other link in the piece of chain you already have.
Bob made the first link. Then, each time he made another link, he connected it to some other link in his piece of chain, exactly as the formula told him to do.
When he finished, he realized that the object he created did not resemble a usual chain at all. In an effort to straighten the chain, he repeatedly took two links which seemed to be at the ends of the chain and tried to pull them apart as far as he could. But there were some more pieces of the “chain” dangling down from the straightened piece at various places.
It was obvious to Bob that his work is not finished yet and he decided to call the object he produced the unfinished chain. After some more pondering, Bob came to a conclusion that he has to break some links and reconnect them to the rest of the unfinished chain more cautiously to obtain a straight chain he aims to produce. In a straight chain, each link is connected to at most two other links and a straight chain cannot be separated into more pieces without breaking a link.
Being now more careful, Bob is going to progress in simple st加粗样式eps. In one step he will choose a link, say A, connected to another link, say B, in the unfinished chain. He will then break A, disconnect it from B and reconnect A to some other link, say C, in the unfinished chain. If there are more links other than B originally connected to A, Bob will keep them connected to A during the whole step.
What is the minimum number of steps Bob has to perform to get a straight chain?

题目大意
给你一颗树,每次操作可以断开一个连接并形成一个新的连接,问最少需要多少次操作可以使得这棵树变成一个链。

思路:
很简单,因为链中要求每个节点的度至多为2,那跑一遍树的所有节点,度数大于2的部分都应该剪掉,将剪掉的部分加和就是答案。可能有人会问为什么不考虑剪下来的部分的度数会改变。在你将度数大于2的部分减下去之后,会将剪下来的部分连在叶子节点上,这样叶子结点的度数由1变成2,对结果没有影响,剪下来的部分中与叶子节点连接的那个节点的度数减一加一其实是没变的,而剪掉部分中的其他节点度数也没变,所以多结果均无影响。

代码:

#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <cmath>
#include <algorithm>
#include<bits/stdc++.h>
using namespace std;
const double N = 1e6+10;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
const inline int read(){
    int k = 0, f = 1; char c = getchar();
    for(;!isdigit(c); c = getchar())
        if(c == '-') f = -1;
    for(;isdigit(c); c = getchar())
        k = k * 10 + c - '0';
    return k * f;
}
#define ll long long
#define CL(a,b) memset(a,b,sizeof(a))
#define MAXN 400010
vector<int> G[MAXN];
int n , x , y , res;
int main()
{
    std::ios::sync_with_stdio(false);
    cin >> n;
    for(int i = 1 ; i < n ; i++)
    {
    	cin >> x >> y;
    	G[x].push_back(y);
    	G[y].push_back(x);
	}
	res = 0;
    for(int i = 1 ; i <= n ; i++)
    {
    	if(G[i].size()>2)
    	{
    		res = res + G[i].size() - 2;
		}
	}
	printf("%d\n",res);
	return 0;
}

E.Zeldain Garden
题目
链接:https://ac.nowcoder.com/acm/contest/7817/E
来源:牛客网

Boris is the chief executive officer of Rock Anywhere Transport (RAT) company which specializes in supporting music industry. In particular, they provide discount transport for many popular rock bands. This time Boris has to move a large collection of quality Mexican concert loudspeakers from the port on the North Sea to the far inland capital. As the collection is expected to be big, Boris has to organize a number of lorries to assure smooth transport. The multitude of lorries carrying the cargo through the country is called a convoy.
Boris wants to transport the whole collection in one go by a single convoy and without leaving even a single loudspeaker behind. Strict E.U. regulations demand that in the case of large transport of audio technology, all lorries in the convoy must carry exactly the same number of pieces of the equipment.
To meet all the regulations, Boris would like to do some planning in advance, despite the fact that he does not yet know the exact number of loudspeakers, which has a very significant influence on the choices of the number and the size of the lorries in the convoy. To examine various scenarios, for each possible collection size, Boris calculates the so-called “variability”, which is the number of different convoys that may be created for that collection size without violating the regulations. Two convoys are different if they consist of a different number of lorries.
For instance, the variability of the collection of 6 loudspeakers is 4, because they may be evenly divided into 1, 2, 3, or 6 lorries.

题目大意:
给出两个数,你要计算出两个数的闭区间中所有数的因子个数的总和。

思路:
数据范围很大,所以就直接写出前几项开始找规律。
1 1 1
2 2 3
3 2 5
4 3 8
5 2 10
6 4 14
7 2 16
8 4 20
发现1-n的因子数就等于n/i的值之和,i从(1-n),y=n/x是一个反比例函数。而横坐标的间隔都是一,高是它的值,所以说要求的结果就可以看成所有矩形的面积加和。它是关于(根号x,根号x)对称,所以取对称一半的面积,画个图就能看出来,前一半的面积的两倍刚好比我们想要求得结果多了个正方形的面积,所以总面积=对称一半的面积2-根号x根号x,

代码:

#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <cmath>
#include <algorithm>
#include<bits/stdc++.h>
using namespace std;
const double N = 1e6+10;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
const inline int read(){
    int k = 0, f = 1; char c = getchar();
    for(;!isdigit(c); c = getchar())
        if(c == '-') f = -1;
    for(;isdigit(c); c = getchar())
        k = k * 10 + c - '0';
    return k * f;
}
#define ll long long
#define CL(a,b) memset(a,b,sizeof(a))
#define MAXN 100010
int n;
char s[400010];
ll solve(ll n)
{
    ll ans=0;
    ll t=sqrt(double(n));
    for(int i = 1 ; i <= t ; i++)
	{
        ans = ans + n/i;
    }
    ans=ans*2-t*t;
    return ans;
}
int main()
{
    std::ios::sync_with_stdio(false);
    ll n , m;
    scanf("%lld %lld",&n,&m);
    ll res = 0;
    res = solve(m) - solve(n-1);
    printf("%lld\n",res);
    return 0;
    
}

鉴于菜的一批,就只做出来这三道题,以下是补题情况:
H.Ponk Warshall
题目:
链接:https://ac.nowcoder.com/acm/contest/7817/H
来源:牛客网

Listening to the rock music permutes your nuclear DNA. This astonishing and unbelievable fact was recently published in the Rock Nature Weekly, one of the top scientific journals on the planet. Part of the research was to take DNA samples from volunteers, both before and after the rock concerts season. The samples were processed and various genes isolated from the samples. For each person, each gene was isolated twice: The variant before the rock season and the variant after the season. These two variants were paired and in many cases one variant was found to be some permutation of the other variant in the pair.
The next step in the research is to determine how the permutations happen. The prevalent hypothesis suggests that a permutation is composed of a sequence of transpositions, so-called swaps. A swap is an event (its chemistry is not fully understood yet) in which exactly two nucleobases in the gene exchange their places in the gene. No other nucleobases in the gene are affected by the swap. The positions of the two swapped nucleobases might be completely arbitrary.
To predict and observe the movement of the molecules in the permutation process, the re- searchers need to know the theoretical minimum number of swaps which can produce a par- ticular permutation of nucleobases in a gene. We remind you that the nuclear DNA gene is a sequence of nucleobases cytosine, guanine, adenine, and thymine, which are coded as C, G, A, and T, respectively.

题意:
只包含A,G,C,T的字符串。要求用最少的交换将S1串变成S2串。

思路
按照网上大神的说法,
AG GA ——> 交换一次减少两个
AG GC CA ——> 交换两次减少3个
AG GC CT TA ——> 交换三次减少4个
就只有这三种情况,跑一遍就成了。

代码;

#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <cmath>
#include <algorithm>
#include<bits/stdc++.h>
using namespace std;
const double N = 1e6+10;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
const inline int read(){
    int k = 0, f = 1; char c = getchar();
    for(;!isdigit(c); c = getchar())
        if(c == '-') f = -1;
    for(;isdigit(c); c = getchar())
        k = k * 10 + c - '0';
    return k * f;
}
#define ll long long
#define CL(a,b) memset(a,b,sizeof(a))
const int maxn = 1e6 + 7;

char a[maxn],b[maxn];
string all[100];
map<string,int>mp;
map<int,char>mp2;
int cnt;
void init() {
    mp2[0] = 'A';
    mp2[1] = 'G';
    mp2[2] = 'C';
    mp2[3] = 'T';
    
    cnt = 0;
    for(int i = 0;i < 4;i++) {
        for(int j = 0;j < 4;j++) {
            if(i == j) continue;
            all[++cnt] += mp2[i];
            all[cnt] += mp2[j];
        }
    }
}
int main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    scanf("%s%s",a + 1,b + 1);
    int n = strlen(a + 1);
    for(int i = 1;i <= n;i++) {
        if(a[i] == b[i]) continue;
        string now;
        now += a[i];now += b[i];
        mp[now]++;
    }
    
    init();
    ll ans = 0;
    
    //1次交换消除2个
    for(int i = 1;i <= cnt;i++) {
        for(int j = 1;j <= cnt;j++) {
            if(i == j) continue;
            if(all[i][1] == all[j][0] && all[j][1] == all[i][0]) {
                int mi = min(mp[all[i]],mp[all[j]]);
                mp[all[i]] -= mi;
                mp[all[j]] -= mi;
                ans += mi;
            }
        }
    }
    
    //两次交换消除3个
    for(int i = 1;i <= cnt;i++) {
        for(int j = 1;j <= cnt;j++) {
            if(i == j) continue;
            for(int k = 1;k <= cnt;k++) {
                if(j == k || j == i) continue;
                if(all[i][1] == all[j][0] && all[j][1] == all[k][0] && all[k][1] == all[i][0]) {
                    int mi = min(mp[all[i]],min(mp[all[j]],mp[all[k]]));
                    ans += mi * 2;
                    mp[all[i]] -= mi;
                    mp[all[j]] -= mi;
                    mp[all[k]] -= mi;
                }
            }
        }
    }
    
    //三次交换消除4个
    for(int i = 1;i <= cnt;i++) {
        for(int j = 1;j <= cnt;j++) {
            if(i == j) continue;
            for(int k = 1;k <= cnt;k++) {
                if(j == k || j == i) continue;
                for(int q = 1;q <= cnt;q++) {
                    if(i == q || j == q || k == q) continue;
                    if(all[i][1] == all[j][0] && all[j][1] == all[k][0] && all[k][1] == all[q][0] && all[q][1] == all[i][0]) {
                        int mi = min(min(mp[all[i]],mp[all[j]]),min(mp[all[k]],mp[all[q]]));
                        ans += mi * 3;
                        mp[all[i]] -= mi;
                        mp[all[j]] -= mi;
                        mp[all[k]] -= mi;
                        mp[all[q]] -= mi;
                    }
                }
            }
        }
    }
    printf("%lld\n",ans);
    return 0;
}

F.Light Emitting Hindenburg
题目:
链接:https://ac.nowcoder.com/acm/contest/7817/F
来源:牛客网

Lothar is organizing a concert tour of his friends’ rock band. The tour will take place in November and each day there will be at most one concert. The tour will be very representative and many musicians are willing to take part in it. The number of musicians in the tour is strictly prescribed and cannot be changed. Each concert on the tour must be attended by all the musicians taking part in the tour.
The good news for Lothar is that the number of candidate musicians is at least as big as the prescribed number of musicians in the tour. The bad news is that a typical musician is not available during the whole month and that various musicians’ schedules differ a lot from each other.
Long ago, Lothar wrote a core of a computer scheduling system, and he is exploiting it now to organize the tour. He repeatedly and somewhat randomly chooses a group of musicians of prescribed size, and lets the system calculate an acceptable tour schedule. The system depends on a very specific data format. The schedules of musicians and the tour schedules are repre- sented as numerical codes. The days in November are labeled by their numbers in the month: 1,2,…,30.
For a given musician, each November day is assigned a particular numerical code. A day with label L is coded by integer 2 30−L if the musician is available on that day. Otherwise, the day is coded by 0. The musician schedule code is the sum of all his or her day codes.
For a given group of musicians, each November day is assigned a particular numerical code. A day with label L is coded by integer 2 30−L if all musicians in the group are available on that day. Otherwise, the day is coded by 0. The group availability code is the sum of all day codes of the group.
For many additional subtle reasons, Lothar thinks that the best tour would be the one with the highest possible value of the availability code of the group of musicians taking part in it.

题意:
给你n个正整数, 让你从中选出k个, 让这k个数字进行按位与操作得到的结果最大.

思路
综合网上各位dalao的思路,将输入的数字以二进制的形式进行存储,用bitset来辅助存储

代码:

#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <cmath>
#include <algorithm>
#include<bits/stdc++.h>
using namespace std;
const double N = 1e6+10;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
const inline int read(){
    int k = 0, f = 1; char c = getchar();
    for(;!isdigit(c); c = getchar())
        if(c == '-') f = -1;
    for(;isdigit(c); c = getchar())
        k = k * 10 + c - '0';
    return k * f;
}
#define ll long long
#define CL(a,b) memset(a,b,sizeof(a))
const int MAXN = 2e5 + 10;
bitset<30> a[MAXN]; //可以将整数转化成二进制补码形式存储.
bool vis[MAXN]; //记录该数值是否被抛弃
int main()
{
    int n, k;
	cin >> n >> k;
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &a[i]);
	}
	for (int i = 29; i >= 0; --i) {
		int cou = 0; //记录当前位为1的个数
		for (int j = 1; j <= n; ++j) {
			if (a[j][i] && !vis[j]) cou++;
		}
		if (cou >= k) {
			for (int j = 1; j <= n; ++j) {
				if (!a[j][i] && !vis[j]) vis[j] = 1;
			}
		}
	}
	int res = -1;
	for (int i = 1; i <= n; ++i) {
		if (!vis[i]) res &= a[i].to_ulong();
	}
	cout << res << endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值