hacz练习赛1

A
题意:给定一个数n,求1到n所有的数连成一个圈,相邻数互质最多,输出对数
题解:因为i和i-1肯定互质,故将i与i-1 连在一起,此时互质对数就是n,即:输出n即可
代码 略。
B

C
题意:判断m是否能被 n 整除。
题解:若m%n=0 输出YES,否则输出NO。
代码 略。
D
题意:给出10个数表示苹果的高度,再给出陶陶的身高,判断出它能够到几个苹果。
题解:判断有几个苹果高度小于陶陶身高+30(板凳的高度)。
代码:

#include<bits/stdc++.h>

using namespace std;

int a[20];

int main(){
	for(int i=1;i<=10;i++) cin>>a[i];
	int x;
	cin>>x;
	int cnt=0;
	for(int i=1;i<=10;i++) 
	if(a[i]<=x+30) cnt++;
	cout<<cnt<<endl;
}

E
题意:给定n个数,每次合并两个数x,y,合并后两个数变成一个数x+y,,并且得到x*y的分数;
题解:不难证明,每次合并两个最大的数最优。
代码:

#include<bits/stdc++.h>

using namespace std;

int a[110];

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	sort(a+1,a+1+n);
	int res=0,x=a[n];
	for(int i=n;i>1;i--){
		res+=x*a[i-1];
		x+=a[i-1];
	}
	cout<<res<<endl;
}

F
可以先学学优先队列再写。
题意:给出若干个进程,一个进程的到达时间,执行时间和运行优先级,按时间先后运行,优先级高的可以打断优先级低的进程,求出全部进程运行结束的先后顺序,
题解:一道裸的运用优先队列进行模拟,按照进度进行即可,若两任务之间时间够前一个完成,则取出队首,再进行计算,若不行则将任务时间减去间隔时间再入队,注意按有限度排列
代码:

#include<bits/stdc++.h>
using namespace std;
struct Node{
	int id,s,w,v;
	bool operator < (const Node& tmp)const{
		if(v==tmp.v) return s>tmp.s;
		return v<tmp.v;
	}
};
priority_queue<Node> q;
long long tim;
int main()
{
//	ios::sync_with_stdio(false);
	int id,s,w,v;
	Node u;
	while(~scanf("%d%d%d%d",&u.id,&u.s,&u.w,&u.v)){
		while(!q.empty()&&q.top().w+tim<=u.s){
			Node tmp=q.top();
			q.pop();
		//	cout<<tim<<"GG"<<endl;
			tim+=tmp.w;
			printf("%d %lld\n",tmp.id,tim);
		}
		if(!q.empty()){
			Node tmp=q.top();
			q.pop(); 
			tmp.w-=u.s-tim;
			q.push(tmp);
		}
		q.push(u);
		tim=u.s;
	}
	while(!q.empty()){
		Node tmp=q.top();
		q.pop();
		tim+=tmp.w;
		printf("%d %lld\n",tmp.id,tim);
	}
	return 0;
}

G
题意:有三个字符串,同理石头剪刀布互相制约,给出这三个字符串的制约关系,m次查询,每次给出一个字符串,求出这个字符串被那个字符串制约,不合法则输出“Fake”。
题解:直接利用map模拟即可。
代码

#include<bits/stdc++.h>

using namespace std;

int a[110];

int main(){
	map<string,string>ma;
	string s1,s2;
	cin>>s1>>s2;
	ma[s2]=s1;
	cin>>s1>>s2;
	ma[s2]=s1;
	cin>>s1>>s2;
	ma[s2]=s1;
	int m;
	cin>>m;
	while(m--){
		string s;
		cin>>s;
		if(ma[s]=="") cout<<"Fake\n";
		else cout<<ma[s]<<endl;
	}
}

G
题意:有两堆石子,两人轮流取,每次只能取奇数个,谁先取完谁获胜,温县手是否能获胜。
题解:考虑还剩下偶数个的情况,先手只能取1,3,9,则偶数的状态一定会转化为奇数的状态,直到持续到最后此时后手就会获胜,考虑一堆石子时候得出结论:奇数先手胜,偶数后手胜。但是两堆石子的话,先后手会发生交换,则得出结论:两堆石子和为奇数时先手胜,否则后手胜。
代码

#include<bits/stdc++.h>

using namespace std;

int a[110];

int main(){
	int n,m;
	while(cin>>n>>m){
		if((n+m)%2==1) cout<<"win\n";
		else cout<<"lose\n";
	}
}

I
题意:给出两个点u,v和一个点p,求出点p在直线uv上的垂足。
题解:根据uv可以求出直线uv的方程,因为要求垂足所以p和垂足连成的直线和直线uv垂直,就可以求出p和垂足的直线方程,联立两个直线方程交点就是垂足。
代码

#include<bits/stdc++.h>

using namespace std;

int a[110];

int main(){
	int t;
	cin>>t;
	while(t--){
		double px,py,x1,x2,y1,y2;
		cin>>px>>py>>x1>>y1>>x2>>y2;
		if(fabs(x1-x2)<0.0000001){
			printf("%.5lf %.5lf\n",x1,py);
		} 
		double k=(y1-y2)/(x1-x2);
		if(fabs(k)<0.000001){
			printf("%.5lf %.5lf\n",px,y1);
			continue;
		}
		double b=y1-k*x1;
		double k1=-1/k;
		double b1=py-k1*px;
		double x=(b-b1)/(k1-k);
		double y=k1*x+b1;
		printf("%.5lf %.5lf\n",x,y);
	}
}

J
题意:一个数轴,每一个储物点会有一些东西,同时它们之间存在距离。
每次给个区间[l,r],查询把这个区间内所有储物点的东西运到另外一个储物点的代价是多少? 比如储物点i有x个东西,要运到储物点j,代价为x
dist( i , j ) dist就是储物点间的距离。
*
题解:利用前缀和,也可以利用树状数组,注意取模,直接模拟。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int mod=1e9+7, N=2e5+5;
int n,m;
ll a[N],w[N],s[N];
int main()
{
	ios::sync_with_stdio(0);
   
    cin>>n>>m;
    for(int i=2;i<=n;i++)
    {
        cin>>a[i];
        a[i]=(a[i]+a[i-1])%mod;
    }
    for(int i=1;i<=n;i++)
    {
        cin>>w[i];
        s[i]=(a[i]*w[i]%mod+s[i-1])%mod;
        w[i]=(w[i]+w[i-1])%mod;
    }
    int x,l,r;
    ll da;
    while(m--)
    {
        cin>>x>>l>>r;
        if(x<=l)
        {
            da=((s[r]-s[l-1]+mod)%mod-(w[r]-w[l-1]+mod)%mod*a[x]%mod+mod)%mod;
        }
        else if(x>=r)
        {
            da=((w[r]-w[l-1]+mod)%mod*a[x]%mod-(s[r]-s[l-1]+mod)%mod+mod)%mod;
        }
        else
        {
            da=((s[r]-s[x-1]+mod)%mod-(w[r]-w[x-1]+mod)%mod*a[x]%mod+mod)%mod;
            da=(da+((w[x]-w[l-1]+mod)%mod*a[x]%mod-(s[x]-s[l-1]+mod)%mod+mod)%mod)%mod;
        }
        cout<<da<<endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值