SDNU&&QLU_ACM_ICPC_2022_Weekly_Practice_4rd「团队赛」2018 宁夏邀请赛

A模拟栈

A - Maximum Element In A Stack

题意:对一个栈进行入栈和出栈操作,对于每次操作求出栈中的最大元素,求 其中i为第i次操作,ai为栈中最大值

思路: 用栈来记录每一层的最大值,注意pop时要记得更新当前层的最大值

#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=5e6+10;
const int inf=0x3f3f3f3f;

using namespace std;
ll st[N],t=-1;//栈记录每一层的最大值
ll ans[N],cnt;

unsigned int ma=0;//ma为当前层的最大值
int n, p, q, m;
unsigned int SA, SB, SC;
unsigned int rng61(){
    SA ^= SA << 16;
    SA ^= SA >> 5;
    SA ^= SA << 1;
    unsigned int t = SA;
    SA = SB;
    SB = SC;
    SC ^= t ^ SA;
    return SC;
}


void PUSH(unsigned int x)
{
    if(x>=ma)
	{
		st[++t]=x;
		ans[++cnt]=x;
		ma=x;
	}
	else
	{
		st[++t]=ma;
		ans[++cnt]=ma;
	}
}
void POP()
{
    if(t==-1)
	{
		ans[++cnt]=0;
		ma=0;
	}
	else
	{
		t--;
		if(t==-1)
		{
			ans[++cnt]=0;
			ma=0;
		}
		else
		{
			ans[++cnt]=st[t];
			ma=st[t];
		}
	}
}
void gen(){
    scanf("%d%d%d%d%u%u%u", &n, &p, &q, &m, &SA, &SB, &SC);
    for(int i = 1; i <= n; i++){
        if(rng61() % (p + q) < p)
            PUSH(rng61() % m + 1);
        else
            POP();
    }
}
void solve(int num)
{
    //memset(mm,0,sizeof mm);
    memset(st,0,sizeof st);
    memset(ans,0,sizeof ans);
	cout<<st[t]<<'\n';
	ma=0,cnt=0,t=-1;
    gen();
    ll ret=0;
    for(int i=1;i<=cnt;i++) ret^=ans[i]*i;
    cout<<"Case #"<<num<<": "<<ret<<'\n';
}   
int main()
{
    //ios;
    int tt=1;
    int _t=1;
    cin>>_t;
    while(_t--)
    {
        solve(tt++);
    }
    system("pause");
    return 0;
}

B几何

 B - Rolling The Polygon

题意: 给你一个n边形n个点的坐标,点Q的坐标(在多边形的内部或边上),求多边形滚动一周后,点Q轨迹的长度。

思路:每次滚动Q的轨迹都是以Pi为圆心,QPi为半径,圆心角为PI-∠Pi的圆弧长。

#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define gen(x) x##_
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define PII pair<int,int>

typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
const double PI=acos(-1);
using namespace std;
struct node{
	double x,y;
}p[55];
node q;
int n;
double d(struct node A,struct node B)
{
	return sqrt(pow(A.x-B.x,2)+pow(A.y-B.y,2));
}
double fun(node B,node A,node C)//求角A的cos值
{
	double a=d(B,C);
	double b=d(A,C);
	double c=d(A,B);
	return (b*b+c*c-a*a)/(2*b*c);
}
void solve(int num)
{
	cin>>n;
	for(int i=1;i<=n;i++) cin>>p[i].x>>p[i].y;
	p[0]=p[n],p[n+1]=p[1];
	cin>>q.x>>q.y;
	double ans=0;
	for(int i=1;i<=n;i++)
	{
		double dis=d(p[i],q);//半径
		double ang=acos(fun(p[i-1],p[i],p[i+1]));//角Pi
		ans+=dis*(PI-ang);
	}
	printf("Case #%d: %.3f\n",num,ans);
}
int main()
{
	//ios;
	int _t=1;
	cin>>_t;
	int cnt=1;
	while(_t--)
	{
		solve(cnt++);
	}
	system("pause");
	return 0;
}

C字符串

C - Caesar Cipher

题意:给你长度为n的明文和密文,再给你长度为m的密文,求这段文字对应的明文

#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define gen(x) x##_
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;

using namespace std;
string s1,a1,s2,a2;
int n,m;
void solve(int num)
{
	cin>>n>>m;
	cin>>a1>>s1;
	int d=s1[0]-a1[0];
	cin>>s2;
	//char ans[10000];
	cout<<"Case #"<<num<<": ";
	for(int i=0;i<m;i++)
	{
		//ans[i]=((s2[i]-'A'-d+26)%26+'A');
		cout<<(char)((s2[i]-'A'-d+26)%26+'A');
	}
	//ans[m]='\0';
	//cout<<ans<<'\n';
	cout<<'\n';
}
int main()
{
	//ios;
	int _t=1;
	cin>>_t;
	int cnt=1;
	while(_t--)
	{
		solve(cnt++);
	}
	system("pause");
	return 0;
}

D概率

D - Take Your Seat

题意:问题一:n个人按序号1~n上飞机,其中1号人会随便找一个座位坐,其他人若发现自己的座位被坐了,也会随机找一个座位去坐,若没被占,就坐到编号所对应的位置上。求最后一个人做到自己位置的概率。

问题二:m个人按任意的顺序上飞机,1号人会随便找一个座位坐,其他人若发现自己的座位被坐了,也会随机找一个座位去坐,若没被占,就坐到编号所对应的位置上。求最后一个人做到自己位置的概率。

思路:问题一:疯子坐飞机问题

当n=1时,概率为1;当n>1时,概率恒为1/2 

问题二:从1~m编号定为ABCD

如果A是最后一个上飞机的,那么前面的人一定是坐在自己的座位上,最后一个人一定坐对概率为1/m

如果A是第i个上飞机的,那么前i-1个人一定坐对,相当于转化成问题一,把A看成疯子最后一人坐对的概率为1/2,则这种情况的概率为1/2*(m-1)/m

所以问题二的概率为1/m+ 1/2*(m-1)/m。

#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define gen(x) x##_
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.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;
void solve(int num)
{
	cin>>n>>m;
	double ans1=0,ans2=0;
	if(n==1) ans1=1;
	else ans1=1.0/2;
	ans2=(1.0*m+1)/(2*m);
	printf("Case #%d: %.6f %.6f\n",num,ans1,ans2);
}
int main()
{
	//ios;
	int _t=1;
	cin>>_t;
	int cnt=1;
	while(_t--)
	{
		solve(cnt++);
	}
	system("pause");
	return 0;
}

F最短路

 F - Moving On

题意:给出每座城的风险,求从u到v的最短路,要求路上经过的城的风险不超过w

思路:floyd算法,先按风险从大到小排序,dp[k][u][v]表示考虑前k座城,从u到v的最短路。可以这么考虑,先考虑从u到v与风险最低的城相连的最短路,再考虑与风险次低的城相连的最短路。。。状态转移方程为dp[k][i][j]=min(dp[k-1][i][j],dp[k-1][i][a[k].id]+dp[k-1][a[k].id][j])

#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define gen(x) x##_
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;

using namespace std;
struct node{
	int id;
	int rob;
}a[210];
int dp[210][210][210];//dp[k][u][v]表示考虑前k座城,从u到v的最短路
int n,q;
bool cmp(node a,node b)
{
	return a.rob<b.rob;
}
void solve(int num)
{
	memset(dp,0x3f,sizeof dp);
	cin>>n>>q;
	for(int i=1;i<=n;i++) cin>>a[i].rob,a[i].id=i;
	sort(a+1,a+n+1,cmp);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>dp[0][i][j];
		}
	}
	for(int k=1;k<=n;k++)
	{
		for(int i = 1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				dp[k][i][j]=min(dp[k-1][i][j],dp[k-1][i][a[k].id]+dp[k-1][a[k].id][j]);//不走第k城,走第k城
			}
		}
	}
	printf("Case #%d:\n",num);
	while(q--)
	{
		int u,v,w;
		cin>>u>>v>>w;
		int k=1;
		for(k=1;k<=n;k++)
		{
			if(a[k].rob>w) break;
		}
		k--;
		cout<<dp[k][u][v]<<'\n';
	}
}
int main()
{
	//ios;
	int _t=1;
	int cnt=1;
	cin>>_t;
	while(_t--)
	{
		solve(cnt++);
	}
	system("pause");
	return 0;
}

H贪心

H - Fight Against Monsters

题意:有n只怪,给出每只怪的生命值和攻击力,英雄可以任选一只怪交战,英雄在与怪交站前,会收到所有怪攻击力总和点伤害,英雄的攻击力是递增的,公差为1,(第一次为1,第二次为2,第三次为3)。求杀死所有怪的情况下,英雄所受的最小伤害。

思路:题目让我们安排打怪的顺序,使英雄所受伤害最小,这很符合贪心的特点,所以我们要按怪的价值进行排序。首先容易想到的是按照怪的攻击力进行排序,但有可能攻击力高的怪血特别厚,英雄会承受很多其他怪的伤害。所以想到要先解决伤害高,所需攻击次数又少的怪,所以怪的价值为怪的攻击力/怪所需攻击次数,也就是平均每次对英雄造成的伤害。

攻击次数可以利用ceil向上取整

#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define gen(x) x##_
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;

using namespace std;
struct node{
	int hp,atk;
	int t;//所需攻击次数
	double w;//怪的价值
}a[N];
int n;
bool cmp(node a,node b)
{
	return a.w>b.w;
}
void solve(int num)
{
	cin>>n;
	ll sum=0;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].hp>>a[i].atk;
		sum+=a[i].atk;
		a[i].t=ceil((-1.0+sqrt(1+8*a[i].hp))/2);//攻击次数向上取整
		a[i].w=a[i].atk*1.0/a[i].t;//怪的价值为平均每次对英雄造成的伤害
	}
	ll ans=0;
	sort(a+1,a+n+1,cmp);
	for(int i=1;i<=n;i++)
	{
		ans+=sum*a[i].t;
		sum-=a[i].atk;
	}
	cout<<"Case #"<<num<<": "<<ans<<'\n';
}
int main()
{
	//ios;
	int _t=1;
	int cnt=1;
	cin>>_t;
	while(_t--)
	{
		solve(cnt++);
	}
	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值