牛客周赛 Round 76

A 小红出题

题意:七天一组,每组前五天每天会出三道题,n天会出多少题。

首先看可以完整过完几周,出题量是n / 7 * 5 * 3, 然后看剩下几天能出几个题。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::cout << (n / 7 * 5 + std::min(5, n % 7)) * 3 << "\n";
}

B 串串香

题意:找一个字符串使得它在s中作为字串出现的次数最多。

对一个子串来说,一个位置只可能作为它的开头一次,那么这个位置上的字符是这个字串的前缀,它作为字串的出现次数肯定是大于等于这个字符串的,所以我们找到字符串越短越好,最短就是一个字符。找s中出现次数最多的字符就行了。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::string s;
    std::cin >> s;
    std::vector<int> cnt(26);
    for (auto & c : s) {
    	++ cnt[c - 'a'];
    }

    char ans = std::max_element(cnt.begin(), cnt.end()) - cnt.begin() + 'a';
    std::cout << ans << "\n";
}

C 小红的gcd

题意:给你一个数组,每次可以选择两个数使得他们变成他们的gcd。

设整个数组gcd为d,那么数组中任意数都可以变成它,这就是最小的数了,所以应该让每个数都变成d。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<i64> a(n);
    i64 d = 0;
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    	d = std::gcd(d, a[i]);
    }

    std::cout << d * n << "\n";
}

D 奇偶调整

这题假了

E 幂次进近

题意:对于给定的n, k,找一个最小的m使得|n - mk|最小。

因为n最大1e18, 对于k大于60的情况差距大于1e18,不如n-1更优,所以这种情况应该输出1。 如果k等于1,那么答案就是n。
其他情况可以二分找到mk小于等于n的最大m,然后把m和m+1比较一下就行了。

点击查看代码
void solve() {
    i64 n, k;
    std::cin >> n >> k;
    if (k > 60) {
    	std::cout << 1 << "\n";
    	return;
    }

    if (k == 1) {
    	std::cout << n << "\n";
    	return;
    }

    using i128 = __int128;
    auto check = [&](i128 x) -> bool {
    	i128 t = 1;
    	for (int i = 1; i <= k; ++ i) {
    		if (t * x > n) {
    			return false;
    		}

    		t *= x;
    	}

    	return true;
    };

    int l = 0, r = 1e9;
    while (l < r) {
    	int mid = l + r + 1 >> 1;
    	if (check(mid)) {
    		l = mid; 
    	} else {
    		r = mid - 1;
    	}
    }

    i128 x = 1, y = 1, min = 4e18;
    for (int i = 1; i <= k; ++ i) {
    	x *= l;
    	y = std::min(y * (l + 1), min);
    }

    if (n - x <= y - n) {
    	std::cout << l << "\n";
    } else {
    	std::cout << l + 1 << "\n";
    }
}

F 同位序列

题意:g(x)是比x大的并且二进制下1的个数和x相等的最小的数,比如g(3) = 5。给你n个数,你要选一些数出来,第一个数随便选,然后每个数x的后面是g(x)。让你选最多的数,并给一种方案。

首先,如何计算g(x)?我们应该加上尽量少的数,如果我们加小于lowbit(x)的数,那么1的个数必然大于x,所以我们至少加上lowbit(x)进行一个进位,然后观察我们需要补多少个1,肯定优先补低位,这样加的数最少。于是我们就是让x加上lowbit(x),然后假设这个数和x差了i个1,那么加上(1 << i) - 1就行。
然后因为g(x)一定比x大,所以我们排序从大到小算,每个数可以排在它的g(x)前面,用map存一下,简单dp就行。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<i64> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    auto lowbit = [&](i64 x) -> i64 {
    	return x & -x;
    };

    auto calc = [&](i64 x) -> int {
    	int cnt = 0;
    	while (x) {
    		if (x & 1) {
    			++ cnt;
    		}

    		x >>= 1ll;
    	}

    	return cnt;
    };

    auto get = [&](i64 x) -> i64 {
    	i64 y = x + lowbit(x);
    	i64 z = calc(x) - calc(y);
    	return y + (1ll << z) - 1;
    };


    std::sort(a.begin(), a.end());
    std::map<int, int> 	f;
    int max = 0, k = 0;
    for (int i = n - 1; i >= 0; -- i) {
    	i64 x = get(a[i]);
    	if (f.count(x)) {
	    	f[a[i]] = f[x] + 1;
    	} else {
    		f[a[i]] = 1;
    	}

    	if (f[a[i]] > max) {
    		max = f[a[i]];
    		k = a[i];
    	}
    }

    std::vector<int> ans;
    while (f.count(k)) {
    	ans.push_back(k);
    	k = get(k);
    }

    std::cout << ans.size() << "\n";
    for (auto & x : ans) {
    	std::cout << x << " \n"[x == ans.back()];
    }
}
posted @   maburb  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示