Codeforces Round 973 (Div. 2)

比赛链接:https://codeforces.com/contest/2013/problem

A. Zhan's Blender


一次最多可以榨汁\(min(x,y)\)水果,答案得解

#include<iostream>
#include<map>
#include<set>
#include<vector>
#include<string.h>
#include<string>
#include<math.h>
#include<queue>
#include<bitset>
#include<stack>
#include<algorithm>
#include<deque>
#include<random>
using namespace std;
typedef long long ll;
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
			ans *= x;
		x *= x;
		y >>= 1;
	}
	return ans; 
}
int main()
{
	ll t;
	cin >> t;
	while (t--)
	{
		ll n,x,y;
		cin >> n >> x >> y;
		ll j = min(x, y);
		ll u = n / j;
		if (n % j > 0)
		{
			u++;
		}
		cout << u << endl;
	}
}

B. Battle for Survive


分析可得,令\(a(n-1)-a(n-2)-...\),最后用\(an\)再减反转下值可以保留最大

#include<iostream>
#include<map>
#include<set>
#include<vector>
#include<string.h>
#include<string>
#include<math.h>
#include<queue>
#include<bitset>
#include<stack>
#include<algorithm>
#include<deque>
#include<random>
using namespace std;
typedef long long ll;
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
			ans *= x;
		x *= x;
		y >>= 1;
	}
	return ans; 
}
ll a[200005];
int main()
{
	ll t;
	cin >> t;
	while (t--)
	{
		ll n;
		cin >> n;
		ll sum = 0;
		for (ll i = 1; i <= n; i++)
		{
			cin >> a[i];
			if (i <= n - 2)
				sum += a[i];
		}
		ll ans = a[n] - a[n - 1] + sum;
		cout << ans << endl;
	}
}

C. Password Cracking


直接假设目前子串为符合子串,如果不可加且长度不够则往前加,最后答案得出

#include<iostream>
#include<map>
#include<set>
#include<vector>
#include<string.h>
#include<string>
#include<math.h>
#include<queue>
#include<bitset>
#include<stack>
#include<algorithm>
#include<deque>
#include<random>
using namespace std;
typedef long long ll;
ll query(string f)
{
	cout << "?" << " " << f << endl;
	cout.flush();
	ll x;
	cin >> x;
	return x;
}
int main()
{
	ll t;
	cin >> t;
	while (t--)
	{
		ll g = 0;
		ll n;
		cin >> n;
		string e = "1";
		if (n == 1)
		{
			if (query(e) == 1)
				cout << "!" << " " << 1 << endl;
			else
				cout << "!" << " " << 0 << endl;
			continue;
		}
		if (query(e) == 0)//一次
			e = "0";
		for (ll i = 2; i <= n; i++)
		{
			string k1,k2;
			k1 = e + '0';k2 = e + '1';
			if (query(k1))
				e = k1;
			else if (query(k2))
				e = k2;
			else
				break;
		}
		while (e.size() != n)
		{
			string k1 = '0'+e, k2 = '1'+e;
			if (query(k1))
				e = k1;
			else
				e = k2;
		}
		cout << "!" << " " << e << endl;
	}
}

E. Prefix GCD


首先显然最小的数放在前面是最佳的,其作为了整体约束。
随后发现不可能每个样例一两下就到最小gcd,思考\(2*3,3*7,2*7\)情况,得三次才有最小gcd,或者类似于2的次方,但是有其他数参杂,最多也就60多次吧(远远达不到这么多)近似于这样,
最多暴力枚举前面可能20多个数即可达到最小gcd,质因数分解找最小合成数(最大约束),随后用map再优化下,答案得解

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#define lowbit(x) (x & -x)
using namespace std;
mt19937 rnd(time(0));
//const ll p=rnd()%mod;
typedef long long ll;
const ll mod=1e9+7;
const ll N=2e5+5;
ll ksm(ll x,ll y)
{
	ll ans=1;
	while(y)
	{
		if(y&1)
		ans=(ans%mod*x%mod)%mod;
		x=x%mod*(x%mod)%mod;
		y>>=1;
	}
	return ans%mod%mod;
}
ll gcd(ll x,ll y)
{
	if(y==0)
	return x;
	else 
	return gcd(y,x%y);
}
void fio()
{
		ios::sync_with_stdio(0);
		cin.tie(0);
		cout.tie(0);
}
bool vi[250000];
ll gs=0;
ll zs[1500000];
map<ll,ll>q,f;
void ola(ll x)
{
	for(ll i=2;i<=x;i++)
	{
		if(!vi[i])gs++,zs[gs]=i,q[i]++;
		for(ll j=1;zs[j]<=x/i;j++)
		{
			vi[zs[j]*i]=1;
			if(i%zs[j]==0)break;
		}
	}
}
ll a[250000];
vector<ll>g[250000];
int main()
{
	fio();
	ola(100000);
	 ll t;
	 cin>>t;
	 while(t--)
	 {
		ll n;
		cin>>n;
		ll cnt=0;
		for(ll i=1;i<=n;i++)
		{
			cin>>a[i];
			vi[i]=0;
			cnt=gcd(cnt,a[i]);
		}
		sort(a+1,a+1+n);
		ll k=a[1];
		ll cf=1;
		vi[1]=1;
		ll ans1=0;
		ans1+=a[1];
		while(k!=cnt)
		{
			ll m=k;
			f.clear();
			ll l=1;
			while(m!=1)
			{
				if(q[m])
				{
					f[m]++;break;
				}
				if(m%zs[l]==0)
				{
					f[zs[l]]++;
					m/=zs[l];
				}
				else l++;
			}
			ll ans=9999999999999;
			ll wz;
			for(ll i=1;i<=n;i++)
			{
				if(vi[i])continue;
				ll u=a[i];
				ll cnt1=1;
				ll l=1;
				ll op=0;
				while(u!=1)
				{
					if(u%zs[l]==0)
					{
						if(op<f[zs[l]])
						{
							op++;
							cnt1*=zs[l];
						}
						u/=zs[l];
					}
					else l++,op=0;
				}
				if(ans>cnt1)
				{
					ans=cnt1;
					wz=i;
				}
			}
			vi[wz]=1;
			k=gcd(k,ans);
			ans1+=k;
			cf++;
		}
		cout<<ans1+(n-cf)*cnt<<endl;
	 }
}
posted @ 2024-10-23 00:21  长皆  阅读(13)  评论(0编辑  收藏  举报