2020 CCPC Henan Provincial Collegiate Programming Contest

A

班委竞选

题意:

#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;

using namespace std;
int n,m;
PII ans[N];//学号,票数
void solve()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		int c,t;
		cin>>c>>t;
		if(ans[c].second<t) ans[c]={i,t};
	}
	for(int i=1;i<=m;i++)
		cout<<ans[i].first<<" \n"[i==m];
}
signed main()
{
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	//ios;
	int _t=1;
	//cin>>_t;
	while(_t--) solve();
	system("pause");
	return 0;
}

 C

我得重新集结部队

题意:

思路:n<=2e3,O(n^2)模拟即可 

注意:1. 出现多只与狂热者距离相同的异虫时,需要选取最早出现的那只。 2. 考虑狂热者距离时不能考虑已经死亡(离开战场)的异虫。 3. 距离平方的极限数据可达 4 × 10^16,使用 double 计算有可能会产生浮点精度误差。但是注意到距离之间只需要比较大小,因而可将所有距离平方,在长整型范围内进行运算,避免精度误差

#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define PII pair<int,int>
#define int long long
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;

using namespace std;
struct node{
	int op;//类型
	int x,y;
	int h,atk,r;
	bool f;//活着?
}a[N];
int n;
void solve()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int op;
		cin>>op;
		if(op==1)
		{
			a[i].op=1;
			cin>>a[i].x>>a[i].y>>a[i].h;
			a[i].f=1;
		}
		else
		{
			a[i].op=2;
			cin>>a[i].x>>a[i].y>>a[i].atk>>a[i].r;
			a[i].f=1;
			ll dis=1e18;int pos=-1;
			for(int j=1;j<i;j++)
			{
				if(a[j].op==1&&a[j].f==1)
				{
					ll d=(a[j].x-a[i].x)*(a[j].x-a[i].x)+(a[j].y-a[i].y)*(a[j].y-a[i].y);
					if(d<dis)
					{
						dis=d;
						pos=j;
					}
				}
			}
			if(pos!=-1)
			{
				a[i].x=a[pos].x;a[i].y=a[pos].y;
				// vector<int>g;
				bool has=0;
				for(int j=1;j<i;j++)
				{
					if(a[j].op==1&&a[j].f==1)
					{
						ll d=(a[j].x-a[pos].x)*(a[j].x-a[pos].x)+(a[j].y-a[pos].y)*(a[j].y-a[pos].y);
						if(a[i].r*a[i].r>=d)
						{
							a[j].h-=a[i].atk*3;
							if(a[j].h<=0) a[j].f=0;
							else has=1;
						}
					}
				}
				if(has) a[i].f=0;
			}
		}
	}
	for(int i=1;i<=n;i++)
		if(a[i].f==1) cout<<"Yes\n";
		else cout<<"No\n";
}
signed main()
{
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	ios;
	int _t=1;
	//cin>>_t;
	while(_t--) solve();
	system("pause");
	return 0;
}

E

发通知

思路:答案若出现在区间内,则答案也可以出现在该区间端点,因此我们只需要考虑端点。由于要对区间进行操作可以考虑到差分。因为数据范围1e9因此需要离散化

#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;

using namespace std;
ll n,k;
map<ll,pair<ll,ll>>mp;//first是人数,second是w
void solve()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	{
		int a,b,w;
		cin>>a>>b>>w;
		mp[a].first++;
		mp[b+1].first--;
		mp[a].second^=w;
		mp[b+1].second^=w;
	}
	ll ans=-1;
	ll cnt=0;
	ll val=0;
	for(auto i:mp)
	{
		cnt+=i.second.first;
		val^=i.second.second;
		if(cnt>=k)
		{
			ans=max(ans,val);
		}
	}
	cout<<ans<<'\n';
}
signed main()
{
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	ios;
	int _t=1;
	//cin>>_t;
	while(_t--) solve();
	system("pause");
	return 0;
}

I

太阳轰炸

扫描二维码关注公众号,回复: 16506756 查看本文章

 思路:每次砸中的概率为\frac{(R1+r)^{2}}{R2^{2}},至少需要砸\left \lceil h/a \right \rceil次。

\left \lceil h/a \right \rceil>n时,不可能摧毁,概率为0

当R2<=R1+r时,一定砸中,概率为1

其他情况根据二项分布计算概率即可。Σ C(n,i)*p^i*q^(n-i)

预处理阶乘,逆元

#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=5e6+10;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
using namespace std;
ll n,R1,R2,r,a,h;
int qmi(int a,int k)
{
	int ret=1%mod;
	while(k)
	{
		if(k&1) ret=(ll)ret*a%mod;
		k>>=1;
		a=(ll)a*a%mod;
	}
	return ret;
}
int fact[N],inv[N];
int fact_p[N],fact_q[N];
void solve()
{
	cin>>n>>R1>>R2>>r>>a>>h;
	ll cnt=(h+a-1)/a;
	if(cnt>n)
	{
		cout<<0<<'\n';
		return ;
	}
	if(R1+r>=R2)
	{
		cout<<1<<'\n';
		return ;
	}
	fact[0]=1;
	for(int i=1;i<N;i++)
		fact[i]=(ll)fact[i-1]*i%mod;
	inv[n]=qmi(fact[n],mod-2)%mod;
	for(int i=n-1;i>=0;i--)
		inv[i]=(ll)inv[i+1]*(i+1)%mod;
	
	ll x1=(R2*R2)%mod,x2=(R1+r)*(R1+r)%mod,x3=(x1-x2+mod)%mod;
	ll t=qmi(x1,mod-2);
	fact_p[0]=fact_q[0]=1;
	for(int i=1;i<=n;i++)
	{
		fact_p[i]=(ll)fact_p[i-1]*x2%mod*t%mod;
		fact_q[i]=(ll)fact_q[i-1]*x3%mod*t%mod;
	}
	ll ans=0;
	for(int i=1;i<=n;i++)
	{
		if(i*a>=h)
		{
			ans=(ans%mod+(ll)fact[n]%mod*inv[i]%mod*inv[n-i]%mod*fact_p[i]%mod*fact_q[n-i]%mod)%mod;
		}
	}
	cout<<ans<<'\n';
}
signed main()
{
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	//ios;
	int _t=1;
	//cin>>_t;
	while(_t--) solve();
	system("pause");
	return 0;
}

B

广告投放

思路: 考虑DP,但注意到人数是整除,取值只有O(sqrt(m))种。所以可以先打出来有意义的数值,然后做个类似于背包的dp就可以了。

f[i][j]表示观看第i集有j个人的最大收益,所以i需要处理到n+1

#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define PII pair<int,int>
#define int long long
typedef long long ll;
const int N=3e5+10;
const int inf=0x3f3f3f3f;

using namespace std;
ll n,m;
ll p[N],d[N];
ll f[2][N];
bool vis[N];
ll val[N];
void solve()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>p[i];
	for(int i=1;i<=n;i++) cin>>d[i];
	int cnt=0;
	vis[m]=1;
	val[++cnt]=m;
	for(int i=m;i>=1;i--)
	{
		if(vis[i])
		{
			for(int j=1;j<=i;j++)
				vis[i/j]=1;
			val[++cnt]=i;
		}
	}
	f[0][m]=0;
	ll ans=0;
	for(int i=1;i<=n+1;i++)
	{
		for(int j=1;j<=cnt;j++)
		{
			if(i!=1) 
			{
				f[i%2][val[j]/d[i-1]]=max(f[i%2][val[j]/d[i-1]],f[(i-1)%2][val[j]]+val[j]*p[i-1]);
				ans=max(ans,f[i%2][val[j]/d[i-1]]);
			}
			f[i%2][val[j]]=max(f[i%2][val[j]],f[(i-1)%2][val[j]]);
			ans=max(ans,f[i%2][val[j]]);
		}
	}
	cout<<ans<<'\n';
}
signed main()
{
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	//ios;
	int _t=1;
	//cin>>_t;
	while(_t--) solve();
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_62615329/article/details/130629249