CF div3 883

题目链接


E2

按值域分治的技巧

前置 : \(f(k , n) = 1 + k + k ^ 2 + ... + k ^ n\)
\(①\) : 假设答案最终的 \(n = 2\) , 对于 \(1 + k + k ^ 2\) , 我们在 \([2 , 10^9]\) 的范围二分 \(k\) 即可
\(②\) : 假设答案最终的 \(n > 2\) , 那么形式至少是 \(1 + k + k ^ 2 + k ^ 3\) , 由于 \(k ^ 3\) 的存在 , \(k\)的范围只能是 \([2 , 10^6]\) , 那么我们枚举 \(k\) , 对于每种 \(k\) , 递增枚举 \(n\) , 不断向 \(set\) 添加\(f(k , n)\) 的值 , 知道\(f(k , n) > 10^{18}\) , 由于指数增加 , 最终 \(set\) 中的个数为\(O(klogk) , k = 10^6\)

对于每个 \(x\) , 先尝试 \(①\) , 再尝试 \(②\) 即可

#include <bits/stdc++.h>
using ll = long long;
const ll INF = 1E18;

int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	
	std::set<ll> p;
	for(ll k = 2 ; k <= 1E6 ; ++k) {
		
		ll w = 1 + k + k * k + k * k * k;
		p.insert(w);
		
		ll base = k * k * k;
		while(true) {
			
			if (base <= INF / k) {
				base *= k;
			} 
			else break;

			if (w + base <= INF) {
				w += base;
				p.insert(w);
			}
			else break;
		}
	}
	
	int t;
	std::cin >> t;
	while (t--) {
		
		ll x ;
		std::cin >> x;
		
		ll l = 2 , r = 1E9;
		while(l < r) {
			ll mid = l + r >> 1;
			if(1 + mid + mid * mid >= x) r = mid;
			else l = mid + 1;
		}	
		
		bool ok = false;
		
		if(1 + r + r * r == x) {
			ok = true;
		} 
		if(!ok && p.count(x)) {
			ok = true;
		}
		
		if(ok) std::cout << "YES\n";
		else std::cout << "NO\n";
		
	}
	
	return 0;	
} 

F

策略 :

$① : $ 先尝试不删除(1次 或 2次) , 那么特殊物品的颜色对应个数会加一
$② : $ 将当前序列中不是这个颜色的删除
$③ : $ 如果特殊物品在 \(②\) 中变色 , 则找到位置 , 否则在尝试一次不删除 , 它必定变色

注意 : \(std::endl\) 可以直接刷新缓存区

#include <bits/stdc++.h>
using ll = long long;

void solve()
{
	int n;
	std::cin >> n;
	
	std::vector<int> ar,Empty;
	std::vector<int> cnt1(10 , 0) , cnt2(10 , 0);
	for(int i = 0 ; i < n ; ++i) {
		int x ; std::cin >> x;
		cnt1[x] += 1;
	}
	
	auto query = [&](int n , std::vector<int> &q) {
		
		std::cout << '-' << ' ' << q.size() ; 
		for(auto x : q) {
			std::cout << ' ' << x + 1; 
		}
		std::cout << std::endl;
				
		std::vector<int> a(n - q.size());
		for(int i = 0 ; i < n - q.size() ; ++i)
			std::cin >> a[i];
		return a;
		
	};
	
	ar = query(n , Empty);
	for(int i = 0 ; i < ar.size() ; ++i) 
		cnt2[ar[i]] += 1;
		
	int col = 0;
	for(int i = 1 ; i <= 9 ; ++i) {
		if(cnt2[i] == cnt1[i] + 1) {
			col = i ; break;
		}
	}
	
	if(col == 0) {
		ar = query(n , Empty);
		fill(cnt2.begin(),cnt2.end(),0);
		for(int i = 0 ; i < ar.size() ; ++i)
			cnt2[ar[i]]++;
		for(int i = 1 ; i <= 9 ; ++i) {
			if(cnt2[i] == cnt1[i] + 1) {
				col = i ; break;
			}
		}
	}
	
	std::vector<int> del;
	for(int i = 0 ; i < ar.size() ; ++i) {
		if (ar[i] != col) {
			del.push_back(i);
		}
	}
	
	ar = query(ar.size() , del);
	
	int ans = 0;
	for(int i = 0 ; i < ar.size() ; ++i) {
		if(ar[i] != col) {
			ans = i + 1 ; break;
		}
	}
	
	if(ans == 0) {
		ar = query(ar.size() , Empty);
		for(int i = 0 ; i < ar.size() ; ++i) {
			if(ar[i] != col) {
				ans = i + 1 ; break;
			}
		}
	} 
	
	std::cout << "! " << ans << std::endl;
		
}
int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	
	int t;
	std::cin >> t;
	while (t--) {
		solve();
	}
	
	return 0;
}

posted @ 2023-07-08 17:08  xqy2003  阅读(25)  评论(0)    收藏  举报