The 2022 ICPC Asia Xian Regional Contest(J、F、C、G、E)

J. Strange Sum

思路:总而言之,就是最多可以取两个元素,因此,排序一遍数组 a a a,然后对比一下 m a x ( 0 , a n − 1 , a n − 1 + a n − 2 ) max(0,a_{n - 1},a_{n - 1} + a_{n - 2}) max(0,an1,an1+an2)即可得出答案。


void solve()
{
	int n; cin >> n;
	vector<int> a(n);

	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}
	sort(a.begin(), a.end());

	cout << max({ 0, a[n - 1], a[n - 1] + a[n - 2] });

}

看到可以选可以不选,最小值可以为 0 0 0了,他可能只有一个正的数,所以有可能只选最大的一个,然后看到任意区间,一定长度,可以选排好序的数组的最后两个数和最后一个数与 0 0 0 对比大小即可。


F. Hotel

思路:模拟实现。无论性别不同,双人间和单人间都有两种方案,都选双人间或者都选单人间

void solve()
{
  int n, c1, c2;
  cin >> n >> c1 >> c2;
  ll sum = 0;
  while (n--)
  {
    string s;
    cin >> s;
    sort(s.begin(), s.end());
    if (s[0] == s[1] || s[1] == s[2])
    {
      sum += min(c1, c2) + min(c1 * 2, c2);
    }
    else
    {
      sum += min(c1, c2) * 3;
    }
  }
  cout << sum << endl;
}

C. Clone Ranran

思路:显然,先克隆再出题方案最佳。

void solve()
{
	ll a, b, c;
	cin >> a >> b >> c;
	ll ans = 1e18;
	for (int i = 1; i <= 31; i++) {
		ll m = ksm(2, i - 1);
		ll sum = (i - 1) * a;
		sum += c / m * b + (c % m != 0) * b;
		ans = min(ans, sum);
	}
	cout << ans << endl;
}

G. Perfect Word

思路:看数据范围,不超过 1 e 5 1e5 1e5,平均每个字符串的长度为 350 350 350 左右,可以暴力。所以这题采取暴力的方式。只要这个字符串所有的子串都存在,这就是个完美的字符串,我们对这些完美字符串取最长即可

void solve()
{
	int n; cin >> n;
	
	map<string, int> mp;
	for (int i = 0; i < n; i++) {
		cin >> s[i];
		mp[s[i]] ++;
	}

	ll res = 0;
	for (int i = 0; i < n; i++) {
		string str = s[i];
		int sz = str.size();
		int flag = 1;
		for (int l = 0; l < sz; l++) {
			for (int r = l + 1; r <= sz; r++) {
				string Ms = str.substr(l, r);
				if (!mp[Ms]) {
					flag = 0;
					break;
				}
			}
			if (!flag) {
				break;
			}
		}
		if (flag) {
			res = max(res, 1ll * sz);
		}

	}
	cout << res << endl;
}

E. Find Maximum

思路:首先,我们打表,发现答案不是很大,因此考虑规律。经观察发现,每一个 f i f_i fi 的值等于 i i i 的三进制的位数和每一位的值相加, 12 ( 10 ) = = 110 ( 3 ) , f [ 12 ] = 2 + 3 = 5 12(10) == 110(3),f[12] = 2 + 3 = 5 12(10)==110(3),f[12]=2+3=5。显然,在一定的位数下,让每一位尽可能的出现 2 2 2 的情况是最优的。因此我们考虑几种情况
1. 1. 1. f [ l ] f[l] f[l] 是有可能大于 f [ r ] f[r] f[r]
2. 2. 2. 尽可能的造出合法的最优解,在每一位不是 0 0 0 上退位,后面的位数全部为 2 2 2 的合法性就有了

vector<int> get(ll x,int u)
{//进制转换 
	vector<int> a;
	while(x){
		int t = x % u;
		a.push_back(t);
		x /= u;
	}
	reverse(a.begin(),a.end());
	return a;
}

ll query(ll x)
{
	if(x == 0) return 1;
	else if(x % 3 == 0) return query(x / 3) + 1;
	else return query(x - 1) + 1;
}

void solve()
{
    ll l,r;
    cin >> l >> r;
    vector<int> vec = get(r,3);
    ll ans = max(query(l),query(r));
    int sz = vec.size();
    //cout << query(l) << ' ' << query(r);
    
    for(int i = 0; i < sz; i ++){
		if(vec[i] == 0) continue;
		ll sum = 0;
		for(int j = 0; j < i; j ++){
			sum = sum * 3 + vec[j];
		}
		sum = sum * 3 + vec[i] - 1;//始终在r之下 
		for(int j = i + 1; j < sz; j ++){
			sum = sum * 3 + 2;
		}
		if(sum >= l && sum <= r){//造的可能小于l 
			ans = max(ans,query(sum));
		}
	}
	cout << ans << endl;
}
  • 22
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值