团队练习记录2024.9.28

B - Magical Subsequence

https://codeforces.com/gym/103447/problem/B
桶+stack,这里用map会TLE
stack用一次时间复杂度\(O(1)\)
\(156ms/1000ms\)

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void fio()
{
	ios::sync_with_stdio();
	cin.tie(0);
	cout.tie(0);
}
ll ksm(ll x,ll y)
{
	ll ans=1;
	while(y)
	{
		if(y&1)
		ans*=x;
		x*=x;
		y>>=1;
	}
	return ans;
}
inline ll read()
{
	ll x = 0, f = 1;
	char ch = getchar();
	while (!isdigit(ch))
	{
		if (ch == '-') 
			f = -1;
		ch = getchar();
	}
	while (isdigit(ch))
	{
		x = (x << 1) + (x << 3) + (ch ^ 48);
		ch = getchar();
	}
	return x * f;
}
ll a[250000];
ll n;
ll ck(ll x)
{
	stack<ll>q;
	ll b[250]={0};
	ll ans=0;
	for(ll i=1;i<=n;i++)
	{
		if(a[i]<x)
		{
			if(b[x-a[i]]>0)
			{
				ans++;
				while(!q.empty())
				{
					b[q.top()]=0;
					q.pop();
				}
				continue;
			}
			else
			{
				if(b[a[i]]==0)
				{
					q.push(a[i]);
				}
				b[a[i]]++;
			}
		}
	}
	return ans*2;
}
int main()
{
cin>>n;;
for(ll i=1;i<=n;i++)a[i]=read();
ll ans=0;
for(ll i=1;i<=200;i++)
{
	ans=max(ans,ck(i));
}
printf("%lld\n",ans);
} 

D. Math master

https://codeforces.com/gym/103447/problem/D
先用gcd求出最小的比例形式,然后暴力求出一个数的所有可能组合,时间复杂度为最差在2的18次方左右?
sort一遍储存的数
然后直接check查出另一个答案是否符合题目要求
第一个符合的最小的即为所求。
\(3171ms/4000ms\)

#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
using namespace std;
typedef  long long ll;
void fio()
{
	ios::sync_with_stdio();
	cin.tie(0);
	cout.tie(0);
}
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;
}
/*
inline ll read()
{
	ll x = 0, f = 1;
	char ch = getchar();
	while (!isdigit(ch))
	{
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (isdigit(ch))
	{
		x = (x << 1) + (x << 3) + (ch ^ 48);
		ch = getchar();
	}
	return x * f;
}*/
ll a[3500000];
ll l = 0;
void zu(string x,ll wz,ll su)
{
	for (ll i = wz + 1; i < x.size(); i++)
	{
		zu(x, i, su * 10 + x[i] - '0');
	}
	if (su > 0)
	{
		l++;
		a[l] = su;
	}
}
bool ck(string a, string b, string a1, string b1)
{
	ll num[15] = { 0 };
	ll num2[15] = { 0 };
	ll la = a.length() - 1, la1 = a1.length() - 1, lb = b.length() - 1, lb1 = b1.length() - 1;

	while (la1 >= 0) {
		if (la < 0) {
			if (a1[la1] == '0' && la < 0) {
				num[10]++;
				la1--;
				continue;
			}
			num[a1[la1] - '0']++;
			la1--;
			continue;
		}

		if (a[la] == a1[la1]) {
			la--, la1--;
			continue;
		}
		else {
			num[a1[la1] - '0']++;
			la1--;
		}
	}
	while (lb1 >= 0) {
		if (lb < 0) {
			if (b1[lb1] == '0' && lb < 0) {
				num2[10]++;
				lb1--;
				continue;
			}
			num2[b1[lb1] - '0']++;
			lb1--;
			continue;
		}
		if (b[lb] == b1[lb1]) {
			lb--, lb1--;
			continue;
		}
		else {
			num2[b1[lb1] - '0']++;
			lb1--;
		}
	}
	ll flag = 1;
	for (int i = 0; i <= 9; i++) {
		if (i == 0) {
			ll mini = min(num[0] + num[10], num2[0] + num2[10]);
			if (mini < max(num[0], num2[0])) {
				flag = 0;
			}
		}
		else if (num[i] != num2[i]) {
			flag = 0;
		}
	}
	if (flag) return true;
	else return false;
}
int main()
{
	fio();
	ll t;
	t = 1;
	while (t--)
	{
		ll n;
		cin >> n;
		for (ll i = 1; i <= n; i++)
		{
			ll x, y;
			cin >> x >> y;
			ll k = gcd(x, y);
			ll x1 = x / k;
			ll y1 = y / k;
			string h = to_string(x);
			string e = to_string(y);l = 0;
			for (ll u = 0; u < h.size(); u++)
			{
				zu(h, u, h[u] - '0');
			}
			//for (ll i = 1; i <= l; i++)cout << a[i] << " ";
			sort(a + 1, a + 1 + l);
			ll ans1=0, ans2=0;
			for (ll i = 1; i <= l; i++)
			{
				if (a[i] % x1 == 0)
				{
					ll k1 = a[i] / x1;
					ll y2 = y1*k1;
					string jk = to_string(a[i]);
					string ko = to_string(y2);
					if (ck(jk,ko,h,e))
					{
						ans1 = a[i], ans2 = y2;
						break;
					}
				}
			}
			cout << ans1 << " " << ans2 << endl;
		}
	}
}

E. Power and Modulo

https://codeforces.com/gym/103447/problem/E
打表可得,如果2的次方被模后会呈现一个周期,要特判后面为为0,全部数为0,数组对应位置大于2的次方的情况
然后直接找到第一个变小的数字,然后用对应的数的次方减掉它即为模数
\(218ms/1000ms\)

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
void fio()
{
	ios::sync_with_stdio();
	cin.tie(0);
	cout.tie(0);
}
ll ksm(ll x,ll y)
{
	ll ans=1;
	while(y)
	{
		if(y&1)
		ans*=x;
		x*=x;
		y>>=1;
	}
	return ans;
}
/*
inline ll read()
{
	ll x = 0, f = 1;
	char ch = getchar();
	while (!isdigit(ch))
	{
		if (ch == '-') 
			f = -1;
		ch = getchar();
	}
	while (isdigit(ch))
	{
		x = (x << 1) + (x << 3) + (ch ^ 48);
		ch = getchar();
	}
	return x * f;
}*/
ll a[120000];
int main()
{
	fio();
	ll t;
	cin>>t;
	while(t--)
	{
		ll n;
		cin>>n;
		ll g=0;
		ll op=0;
		for(ll i=1;i<=n;i++)
		{
			cin>>a[i];
			if(a[i]==0)
			op++;
			if(g)
			{
				if(a[i]>0)
				{
					g=-1;
				}
			}
			if(a[i]==0&&g==0)
			{
				g=1;
			}
		}
		if(op==n)
		{
			cout<<1<<endl;
			continue;
		}
		if(g==-1)
		{
			cout<<-1<<endl;
			continue;
		}
		ll cnt=1;
		ll x=0;
		for(ll i=1;i<=n;i++)
		{
			if(a[i]!=cnt)
			{
			x=cnt-a[i];
			break;	
			}
			cnt*=2;
		}
		if(x<0)
		{
			cout<<-1<<endl;
			continue;
		}
		if(x==0)
		{
			x=a[n];
		}
		 cnt=1;
		g=0;
		cnt%=x;
		for(ll i=1;i<=n;i++)
		{
			if(a[i]!=cnt)
			{
	     	g=-1;		
			}
			cnt=(cnt%x*(2%x))%x;
		}
		if(g==-1)
		{
			cout<<-1<<endl;
		}
		else
		{
			cout<<x<<endl;
		}
	}
}

I. Power and Zero

https://codeforces.com/gym/103447/problem/I
二进制转换+暴力
记得没事不开\(unsigned long long\)
\(249ms/1000ms\)

#include<iostream>
using namespace std;
typedef  long long ll;
void fio()
{
	ios::sync_with_stdio();
	cin.tie(0);
	cout.tie(0);
}
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
			ans *= x;
		x *= x;
		y >>= 1;
	}
	return ans;
}
/*
inline ll read()
{
	ll x = 0, f = 1;
	char ch = getchar();
	while (!isdigit(ch))
	{
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (isdigit(ch))
	{
		x = (x << 1) + (x << 3) + (ch ^ 48);
		ch = getchar();
	}
	return x * f;
}*/
ll a[40];
int main()
{
	fio();
	ll t;
	cin >> t;
	//	cout<<55<<endl;
	while (t--)
	{
		ll n;
		cin >> n;
		for (ll i = 0; i <= 31; i++)a[i] = 0;
		for (ll i = 1; i <= n; i++)
		{
			ll x;
			cin >> x;
			ll k = 1;
			for (ll j = 0; j <= 31; j++)
			{
				if (k & x)
					a[j]++;
				k *= 2;
			}
		}
		ll ans = 0;
		while (1)
		{
			ll cnt = 0;
			for (ll i = 0; i <= 31; i++)
			{
				if (a[i] == 0)
					cnt++;
			}
			if (cnt == 32)
				break;
			ans++;
			for (ll i = 0; i <= 31; i++)
			{
				if (a[i] > 0)
				{
					a[i]--;
				}
				else
				{
					for (ll j = i + 1; j <= 31; j++)
					{
						if (a[j] > 0)
						{
							a[j]--;
							for(ll k = j - 1; k >= 0; k--)
							{
								if (k >= i)
								{
									a[k]++;
								}
								else
								{
									break;
								}
							}
							break;
						}
					}
				}
			}
		}
		cout << ans << endl;
	}
}

J. Local Minimum

https://codeforces.com/gym/103447/problem/J
统计一个数既为此行最小和此列最小的数
\(203ms/1000ms\)

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void fio()
{
	ios::sync_with_stdio();
	cin.tie(0);
	cout.tie(0);
}
ll ksm(ll x,ll y)
{
	ll ans=1;
	while(y)
	{
		if(y&1)
		ans*=x;
		x*=x;
		y>>=1;
	}
	return ans;
}
inline ll read()
{
	ll x = 0, f = 1;
	char ch = getchar();
	while (!isdigit(ch))
	{
		if (ch == '-') 
			f = -1;
		ch = getchar();
	}
	while (isdigit(ch))
	{
		x = (x << 1) + (x << 3) + (ch ^ 48);
		ch = getchar();
	}
	return x * f;
}
ll a[2500][2500];
ll b[2500];
ll c[2500];
int main()
{
	ll n,m,f;
	n=read();
	m=read();
	for(ll i=1;i<=n;i++)
	{
		ll x=99999999999;
		for(ll j=1;j<=m;j++)
		{
			a[i][j]=read();
			x=min(x,a[i][j]);
		}
		b[i]=x;
	}
     for(ll i=1;i<=m;i++)
	{
		ll x=99999999999;
		for(ll j=1;j<=n;j++)
		{
			x=min(x,a[j][i]);
		}
		c[i]=x;
	}
	ll ans=0;
	for(ll i=1;i<=n;i++)
	{
		for(ll j=1;j<=m;j++)
		{
			if(b[i]==a[i][j]&&c[j]==a[i][j])
			ans++;
		}
	}
	printf("%lld\n",ans);
} 
posted @ 2024-09-28 18:40  长皆  阅读(14)  评论(0编辑  收藏  举报