2020ICPC南京站

K

K Co-prime Permutation

题意:给定n和k,让你构造n的排列,满足gcd(pi, i)=1的个数为k。

思路:因为x和x-1互质,1和任何数互质,任何数和它本身不互质

当k为奇数时,p1=1,后面k-1个数两两互换

当k为偶数时,后面k个数两两互换

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

using namespace std;
int n,k;
int a[N];
void solve()
{
	cin>>n>>k;
	if(k==0)
	{
		cout<<-1<<'\n';
		return ;
	}
	int cnt=0;
	for(int i=1;i<=n;i++) a[i]=i;
	if(k&1)
	{
		cnt=1;
		for(int i=2;i<=n&&cnt>_t;
	while(_t--) solve();
	system("pause");
	return 0;
}

L

Let's Play Curling

题意:给定n块红色石头,m块蓝色石头的位置。记红色石头的位置为a[i],蓝色石头的位置为b[i]。当红色石头到目标位置c的距离比蓝色所有石头到目标位置的距离都要小时,计一分,找到一个c点可以让红队尽可能多赢,输出红队尽可能多赢的次数。

思路:在两块蓝色石头之间一定存在一个位置满足条件,得分为两个蓝色石头之间红色石头的个数。

即求两个蓝色石头之间最多有几个红色石头。

排序后枚举蓝色石头的位置p,二分红色石头找到上下界。

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

using namespace std;
int n,m;
void solve()
{
	cin>>n>>m;
	vectora,b;
	for(int i=1;i<=n;i++)
	{
		int x;
		cin>>x;
		a.push_back(x);
	}
	for(int i=1;i<=m;i++)
	{
		int x;
		cin>>x;
		b.push_back(x);
	}
	b.push_back(0);
	b.push_back(1e9+10);
	sort(a.begin(),a.end());
	sort(b.begin(),b.end());
	int ans=0;
	for(int i=0;i<=m;i++)
	{
		int l=upper_bound(a.begin(),a.end(),b[i])-a.begin();
		int r=lower_bound(a.begin(),a.end(),b[i+1])-a.begin();
		ans=max(ans,r-l);
	}
	
	if(ans==0) cout<<"Impossible\n";
	else cout<>_t;
	while(_t--) solve();
	system("pause");
	return 0;
}

E

Evil Coordinate

题意:初始位置为(0, 0),给定陷阱位置(x, y)和操作字符串。让我们重排列操作字符串使得不陷入陷阱。

思路:设最终位置为(X, Y)若有解则(X, Y)与(x, y)至少有一维坐标不同,我们可以先走不同的那个方向,再走相同的那个方向。所以我们可以将相同操作排在一起,然后枚举UDLR的全排列就可以。

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

using namespace std;
int x,y;
string s;
int dir[4][2]={0,1,0,-1,-1,0,1,0};
char op[4]={'U','D','L','R'};
mapcnt;
string ans;
bool check(vectorv)
{
	ans.clear();
	int X=0,Y=0;
	for(int i=0;i<4;i++)
	{
		for(int j=0;j>x>>y;
	cin>>s;
	if(x==0&&y==0)
	{
		cout<<"Impossible\n";
		return ;
	}
	cnt.clear();
	for(int i=0;iv={0,1,2,3};
	bool f=0;
	do
	{
		if(check(v))
		{
			f=1;
			break;
		}
	} while (next_permutation(v.begin(),v.end()));
	if(!f)
	{
		cout<<"Impossible\n";
		return ;
	}
	else cout<>_t;
	while(_t--) solve();
	system("pause");
	return 0;
}

F

Fireworks

题意:小明做一个烟花花费n的时间,点燃所有做好的烟花花费m的时间。每个烟花有p*10^{-4}的概率是完美的。求最优策略下最小时间花费。

思路:假设最优策略是每生产k个再一起点燃,那么释放一次成功的概率为1-(1-p)^k  (p=p*1e-4).

释放几次后得到完美的期望满足几何分布。

几何分布:在n次伯努利试验中, 试验k次才得到第一次成功的概率。详细的说,是:前k-1次皆失败, 第k次成功的概率。 期望E(x)=1/p;(概率论公式,不再赘述)

那么答案为E(x)*(nk+m)= (nk+m) / [1-(1-p)^k]

接下来三分寻找答案的最小值。

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

using namespace std;
double n,m;
double p;
double qmi(double a,int k)
{
	double ret=1;
	while(k)
	{
		if(k&1) ret=ret*a;
		k>>=1;
		a=a*a;
	}
	return ret;
}
double get(int k)
{
	double t=1.0-qmi(1.0-p,k);
	if(t==0) return (double)0x3f3f3f3f;
	return (k*n*1.0+m)/t;
}
void solve()
{
	cin>>n>>m>>p;
	p=p*1e-4;
	double ans=(double)0x3f3f3f3f3f3f3f3f;
	int l=1,r=1e9;
	while(r>l)
	{
		int lmid=l+(r-l)/3,rmid=r-(r-l)/3;
		double f1=get(lmid),f2=get(rmid);
		ans=min(ans,min(f1,f2));
		if(f1>_t;
	while(_t--) solve();
	system("pause");
	return 0;
}

你可能感兴趣的:(c++,开发语言,算法,数据结构)