ICPC2024昆明站

H. Horizon Scanning

  • 这道题答案有单调性不假,可是也不是有单调性就一定要二分的吧?貌似直接取最小值就好了呀……
#include <bits/stdc++.h>
using namespace std;
const double pi=acos(-1);
struct t1
{
	double x,y;
	double r;
}t[400005];
bool cmp(t1 a,t1 b)
{
	return a.r<b.r;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		int n,k;
		cin>>n>>k;
		for(int i=1;i<=n;i++)
		{
			cin>>t[i].x>>t[i].y;
			if(t[i].x>=0&&t[i].y>0)
			{
				t[i].r=pi/2-(atan(t[i].x/t[i].y));
			}
			else if(t[i].x<0&&t[i].y>=0)
			{
				t[i].r=pi-atan(-t[i].y/t[i].x);
			}
			else if(t[i].x<=0&&t[i].y<0)
			{
				t[i].r=pi+(pi/2-atan(t[i].x/t[i].y));
			}
			else if(t[i].x>0&&t[i].y<=0)
			{
				t[i].r=2*pi-atan(-t[i].y/t[i].x);
			}
		}
		sort(t+1,t+n+1,cmp);
		for(int i=1;i<n;i++)
		{
			t[i+n]=t[i];
			t[i+n].r+=2*pi;
		}
		double l=0,r=2*pi;
		int eps=100;
		while(eps--)
		{
			double mid=(l+r)/2;
			bool f=true;
			for(int i=1;i<=n;i++)
			{
				auto check=[i,mid](t1 x)
				{
					return x.r-t[i].r<mid;
				};
				int p=partition_point(t+i,t+n+i,check)-1-t;
				if(p-i<k)
				{
					f=false;
					break;
				}
			}
			if(f==true)
			{
				r=mid;
			}
			else
			{
				l=mid;
			}
		}
		cout<<fixed<<setprecision(10)<<l<<"\n";
	}
	return 0;
}

L. Last Chance: Threads of Despair

  • and each of his minions can attack any one minion from the opposing faction at most once. 是指每个己方势力总共只能攻击一次,而不是每个己方势力都可以攻击每个敌方势力各一次
  • 引理:必然存在一种方案使得我方先进行所有攻击操作,此后不断发生爆炸直到对方所有单位清空
  • 证明:如果一个操作方案中,在某次攻击之前发生过爆炸,那么我们将此次攻击移动到所有攻击之前,效果不变,同时也不会导致原本的其他操作失效
  • 模拟一次攻击操作太麻烦了,有没有什么更简便的做法呢?当然有了,把己方健康值-1和敌方健康值-1分离。先把己方的攻击次数统一提取出来,再贪心地分配给敌方就好啦。
#include <bits/stdc++.h>
using namespace std;
int a[500005],b[500005],n,m;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n>>m;
		int tot=0;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
			tot+=(a[i]>1);
		}
		sort(a+1,a+n+1);
		tot+=(a[1]==1);
		for(int i=1;i<=m;i++)
		{
			cin>>b[i];
		}
		sort(b+1,b+m+1);
		int p=0,q=0,cur=0;
		while(q<m)
		{
			while(p<n&&a[p+1]-1<=cur)
			{
				p++;
				cur++;
			}
			if(b[q+1]>cur)
			{
				tot-=(b[q+1]-cur);
				if(tot<0)
				{
					break;
				}
			}
			q++;
			cur++;
		}
		q==m? cout<<"Yes\n":cout<<"No\n";
	}
	return 0;
}

G. GCD

  • 一开始没什么思路。午休的时候躺在床上想,你精通GCD和各种动态规划,居然想不到做法,而且榜单上还能有200多个队伍过题,会不会答案是有限的,直接搜索就好了呢?一试,真的通过了!看来,根据榜单上的过题人数感受题目大致的做法,是一项远被之前的你低估的能力。大家其实也都不太会猜,你看学校的主力队伍交了快10次才在比赛即将结束的时候通过呢
#include <bits/stdc++.h>
using namespace std;
int ans,cur;
void solve(long long a,long long b)
{
	if(cur>=ans)
	{
		return;
	}
	if(a==0)
	{
		ans=min(ans,cur+1);
		return;	
	}
	if(b%a==0)
	{
		ans=min(ans,cur+2);
		return;
	}
	int g=__gcd(a,b);
	cur++;
	solve(a-g,b);
	solve(a,b-g);
	cur--;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		long long a,b;
		cin>>a>>b;
		ans=20;
		cur=0;
		solve(a,b);
		cout<<ans<<"\n";
	}
	return 0;
}

C. Coin

  • 倒序思考+数论分块,很轻松就解决啦~有什么难的呢?
#include <bits/stdc++.h>
using namespace std;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		long long n,k;
		cin>>n>>k;
		long long cur=k-1;
		if(cur>=n)
		{
			cout<<n<<"\n";
			continue;
		}
		else
		{
			while(cur+cur/(k-1)+(cur%(k-1)>0)<=n)
			{
				if(cur%(k-1)&&cur/(k-1)==(cur+cur/(k-1)+1)/(k-1))
				{
					long long cnt=min(n-cur,k-1-cur%(k-1))/(cur/(k-1)+1);
					cur=cur+cnt*(cur/(k-1))+cnt;
					continue;
				}
				cur=cur+cur/(k-1)+(cur%(k-1)>0);
			}
			cout<<cur<<"\n";
		}
	}
	return 0;
}

E. Extracting Weights

  • 原来所谓的金银牌分界题,也不过是个简简单单的高斯消元罢了~
#include <bits/stdc++.h>
using namespace std;
vector<int>a[305];
int c[305*305][305],tmp[305*305][305];
int n,m,k;
int q[305];
bool Gauss()
{
	memcpy(tmp,c,sizeof(tmp));
	for(int i=1;i<=n;i++)
	{
		for(int j=i;j<=m;j++)
		{
			if(c[j][i]>0)
			{
				swap(c[i],c[j]);
				break;
			}
		}
		if(!c[i][i])
		{
			return false;
		}
		q[i]=c[i][n+2];
		for(int j=1;j<=m;j++)
		{
			if(i!=j&&c[j][i])
			{
				for(int k=1;k<=n;k++)
				{
					c[j][k]^=c[i][k];
				}
			}
		}
	}
	memcpy(c,tmp,sizeof(c));
	return true;
}
void Gauss(int n)
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(i!=j&&c[j][i])
			{
				for(int k=1;k<=n+1;k++)
				{
					c[j][k]^=c[i][k];
				}
			}
		}
	}
	cout<<"!";
	for(int i=2;i<=n;i++)
	{
		cout<<" "<<c[i][n+1];
	}
	cout<<endl;
}
int s[305];
void dfs(int n1,int dep,int fa)
{
	s[dep]=n1;
	if(dep==k)
	{
		m++;
		c[m][0]=s[0];
		for(int i=0;i<=k;i++)
		{
			c[m][s[i]]=1;
		}
		c[m][n+1]=s[k];
		c[m][n+2]=m;
		return;
	}
	for(int i=0;i<a[n1].size();i++)
	{
		if(a[n1][i]!=fa)
		{
			dfs(a[n1][i],dep+1,n1);
		}
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>k;
	for(int i=1;i<n;i++)
	{
		int u,v;
		cin>>u>>v;
		a[u].push_back(v);
		a[v].push_back(u);
	}
	m=1;
	c[1][1]=1;
	for(int i=1;i<=n;i++)
	{
		dfs(i,0,0);
	}
	if(Gauss())
	{
		cout<<"YES"<<endl;
		cout<<"? "<<n-1;
		for(int i=2;i<=n;i++)
		{
			cout<<" "<<c[q[i]][0]<<" "<<c[q[i]][n+1];
		}
		cout<<endl;
		for(int i=2;i<=n;i++)
		{
			int w;
			cin>>w;
			c[q[i]][n+1]=w;
			memcpy(tmp[i],c[q[i]],sizeof(tmp[i]));
		}
		memcpy(c,tmp,sizeof(c));
		Gauss(n);
	}
	else
	{
		cout<<"NO"<<endl;
	}
	return 0;
}
posted @ 2025-02-24 21:04  D06  阅读(310)  评论(0)    收藏  举报
//雪花飘落效果