湖南大学第十六届程序设计竞赛(补题)

2021.7.15 13-18 p.m.

A Triangles

题意 :给出三个点坐标判断三角形形状(可能不能构成三角形)、

思路
首先判断三点确定的直线斜率是否相等,防止除法精度丢失,化成乘法 (x0-x1)(y1-y2)==(x1-x2)(y0-y1)
判断形状直接算出 三边的长度的平方 ,用最大边的余弦定律判断形状

代码如下:

#include<bits/stdc++.h>

#define ri  int
typedef int lll;
typedef long long ll;

using namespace std;

const ll mod=1e9+7;
inline ll gcd(ll a,ll b) {
	return (!b)?a:gcd(b,a%b);
}
const ll inf=999999999;

int read() {
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x*f;
}
void write(int x) {
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}
ll t;

ll x[3],y[3];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
	
    cin >> t;
    while(t--)
    {
	for(ri i=0;i<3;i++) cin >> x[i] >> y[i];
		
	if((x[0]-x[1])*(y[1]-y[2])==(x[1]-x[2])*(y[0]-y[1]))  //斜率相等公式交叉相乘
	cout << "invalid\n";
	else
	{
	    ll len[3];
	    len[0]=(x[0]-x[1])*(x[0]-x[1])+(y[0]-y[1])*(y[0]-y[1]);
	    len[1]=(x[0]-x[2])*(x[0]-x[2])+(y[0]-y[2])*(y[0]-y[2]);
	    len[2]=(x[1]-x[2])*(x[1]-x[2])+(y[1]-y[2])*(y[1]-y[2]);
	    sort(len,len+3);
	    ll ans=len[0]+len[1]-len[2];  //余弦定律
	    if(!ans) cout << "right\n";
	    else if(ans>0) cout << "acute\n";
	    else cout << "obtuse\n";
	}
    }
    return 0;
}

B Yuki with emofunc and playf

题意 :初始有一个数1,你每次可以将其×10或者+(x−1)现在给你x,问最少经过多少步能到达n或n的倍数。

思路 :看成(k*10)%n=0 || (k+x-1)%n=0 || k%n=0 三种情况,
也就是化成余数0 -- n-1 ,从k%n开始到0的最短路,每一种方式长度均为1,求出最早到0时的dis[0],即为最短距离

代码如下:

#include <bits/stdc++.h>
#define ri  int

typedef int lll;
typedef long long ll;
using namespace std;

const ll mod=1000000007;
const ll inf=999999999;

const ll N=5e5+5;



ll n,x; 

int main()
{   
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    
    cin >> n >> x; --x;
    
    ll k=1;
    vector<ll> vis(n+5);
    vector<ll> dis(n+5);
    
    k=k%n;            //从k%n开始
    queue<ll> q;q.push(k);
	dis[k]=0,vis[k]=1;
    
    ll now=0,tp=0;
    while(!q.empty())
    {
        if(vis[0]) break;   //最早到0的结果输出即可
    	tp=q.front();q.pop();
    	
    	now=(tp+x)%n;
    	if(!vis[now]) q.push(now),vis[now]=1,dis[now]=dis[tp]+1;
    	
    	now=(tp*10)%n;
    	if(!vis[now]) q.push(now),vis[now]=1,dis[now]=dis[tp]+1;
    }
    
    if(!vis[0]) cout << "-1\n";   //到不了0即不存在
    else cout << dis[0] << '\n';
    return 0;
}

D Queuing

题意 : 给出所在队伍当前的位置(第n位),去m个窗口重新排队,且如果一开始A在B前面,并且A和B冲到同一个窗口,那么A还在B前面
问去窗口排队后所在位置的期望值

思路 :一个窗口时增加位置数,发现每次都加一,两个窗口时增加位置数,发现每次都加1/2。
任何窗口数处于第一位,总是一,故推得公式1+(m-1)*(1.0/n)

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <cmath>
#include <set>
#include <stack>
#include <queue>
#define ri  int

typedef int lll;
typedef long long ll;
using namespace std;

const ll mod=80112002;
const ll inf=999999999;

const ll N=5e4+5;

ll t;
ll n,m;
float ans;
int main()
{   
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    
    scanf("%lld%lld",&n,&m);
    float add=1.0/n;
    ans=1+(m-1)*add;
    printf("%.8f",ans);
    return 0;
}

F Team

题意 : 三个大数相加

思路 :大数相加板子,签到题

代码如下:

#include<bits/stdc++.h>

#define ri  int

using namespace std;
typedef int lll;
typedef long long ll;

const ll mod=1e9+7;
inline ll gcd(ll a,ll b) {
	return (!b)?a:gcd(b,a%b);
}
const ll inf=999999999;

vector<ll> add(vector<ll> &A , vector<ll> &B)
{
	ll lena=A.size();
	ll lenb=B.size();
	vector<ll> C;
	ll t=0;
	for(int i=0;i<lena||i<lenb;i++)
	{
		if(i<lena) t+=A[i];
		if(i<lenb) t+=B[i];
		C.push_back(t%10);
		t/=10;
	}
	if(t) C.push_back(1);
	return C;
}

ll t;
string a,b,c;
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	vector<ll> A,B,C,D,E;
	cin >> a >> b >> c;
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
	for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
	C=add(A,B);
	for(ri i=c.size()-1;i>=0;i--) D.push_back(c[i]-'0');
	E=add(C,D);
	for(ri i=E.size()-1;i>=0;i--) cout << E[i];
	cout << '\n';
	return 0;
}

I Binbin and Balls

题意 :有两个球,n层楼,丢球测试出球在多少层为碎的临界点,求最坏情况的最小次数

思路 :由于只有两个球,令可以尝试K次
第一次从第K层丢出 ,如果碎了,第二个球要从1 -> K-1逐个尝试,一共尝试K次。如果没碎,再从第K+K-1层丢出,碎了第二个球从k+1 -> 2k逐个尝试,一共也是K次
因此:尝试K次最多可以试出 k+k-1+k-2+ ... +1层楼

故在给定范围中,用二分查找找出第一个大于等于n楼层的数即为答案。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <cmath>
#include <set>
#include <stack>
#include <queue>
#define ri  int

typedef int lll;
typedef long long ll;
using namespace std;

const ll mod=80112002;
const ll inf=999999999;

const ll N=5e4+5;

ll t;
ll n;
int main()
{   
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    
    cin >> t;
    while(t--)
    {
    	cin >> n;
	ll l=0,r=2e9;
	while(l<r)
	{
	    ll mid=l+r>>1;
	    if(mid*(mid+1)/2>=n) r=mid;   //k+k-1+k-2+k-3 + ... + 1 >= n
	    else l=mid+1;	
	}	
	cout << l << '\n';
    }
    return 0;
}

L Cracked Pipes

题意 :六种类型水管,判断给定的种类排列能否把水从起点运送到终点

思路
一道纯模拟题,比赛时看都没看,不过模拟过程有小技巧
建图,分管道种类,用方向数组进行dfs,能否进入下一段还要检查是否两者能连接上,最后能到终点即输出"YES" ,不能则输出"NO"

代码如下:

#include <bits/stdc++.h>
#define ri  int

typedef int lll;
typedef long long ll;
using namespace std;

const ll mod=80112002;
const ll inf=999999999;

const ll N=5e4+5;

ll n,m;
ll nx[7][4]={{},{-1,0,0,1},{0,-1,1,0},{0,0,1,1},{-1,-1,0,0},{-1,-1,1,0},{0,-1,1,1}};

ll dx[4]={-1,0,0,1};
ll dy[4]={0,-1,1,0};
vector<vector<ll> > mp;
vector<vector<ll> > vis;

void dfs(ll x,ll y)
{
    if(vis[n][m]) return;
    vis[x][y]=1;
	
    ll xx=0,yy=0;
    for(ri i=0;i<4;i++)
    {
        xx=x+dx[i],yy=y+dy[i];
	if(xx>=1&&xx<=n && yy>=1&&yy<=m)
	{
	    if(!vis[xx][yy])
	    {
		if(nx[ mp[x][y] ][i] && nx[ mp[xx][yy] ][3-i]) dfs(xx,yy);
	    }
        }
    }
}
int main()
{   
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    
    cin >> n >> m;
    mp.resize(n+5);vis.resize(n+5); 
    for(ri i=1;i<=n;i++)
    {
    	mp[i].resize(m+5);vis[i].resize(m+5);
    	for(ri j=1;j<=m;j++)
    	{
    		cin >> mp[i][j];
	}
    }
    mp[1][0]=mp[n][m+1]=2;
	
    dfs(1,0);
    if(vis[n][m]&&(mp[n][m]==2||mp[n][m]==5||mp[n][m]==6)) cout << "YES\n";
    else cout << "NO\n";
	
    return 0;
}
posted @ 2021-07-18 11:28  gonghw403  阅读(50)  评论(0编辑  收藏  举报