备赛日记 CCPC2022 高职专场 ABDEHIJK 8/12

A CCPC

手速题

x = input()
y = "CCPC"
if y in x :
    print("Hello CCPC!")
else :
    print("This is not my CCPC")

 B 道路

D国有n个城市,由于城市之间并没有公路,交通十分不方便。

D国国王希望修建n−1条公路,使得对于任意两个城市,都可以通过公路互相到达。

建造公路的任务由各个城市负责,具体来说,每个城市都会给出建造公路的费用,第i个城市修建公路的费用为di​。而对于一条连接x,y两座城市的公路,它的建造任务会由x,y两座城市中修建费用较小的城市来负责修建。整个建造方案的费用为每条公路的建造费用之和。

工程师给出了一个建造方案,但国王认为方案成本略高,他希望工程师修改方案。但出于某种原因,工程师只能在方案中更改不超过k条公路,并且要保证更改后任意两座城市仍然可以通过公路相互到达。你能帮助他算一算在更改方案后最小的建造费用吗?

输入格式:

第一行输入两个正整数n,k(1≤n≤105,0≤k<n)。

接下来一行输入n个正整数di​(1≤di​≤n)表示第i个城市建造公路的费用。

接下来n−1输入初始的建造方案,每个行包含两个正整数x,y(1≤x,y≤n),代表初始建造方案。保证输入是一个合法的方案。

输出格式:

输出一行一个正整数表示最小的成本。

思路:

        将大的边换成最小的边即可,因为输入的方案数保证连通的,删除花费最大的边后与花费最小的顶点连接即可

#include <iostream>
#include <queue>
#include <vector>

#define MAX_V 100002

using namespace std;

int n,k,price[MAX_V];

int main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);
	
	cin>>n>>k;
	int minn=1<<30;
	for(int i=1;i<=n;i++)
	{
	 	cin>>price[i];
	 	minn=min(minn,price[i]);
	}
	
	
	priority_queue<int>que;// 大顶堆

	
	long long ans=0 ;
	
	for(int i=1;i<n;i++){
		int u,v;
		cin>>u>>v;
		ans+=min(price[u],price[v]);
		que.push(min(price[u],price[v]));
	}
	
	while(k--){
		//将最大的边取出
		ans-=que.top();que.pop();
		ans+=minn; 
	}
	
	cout<<ans;
	
	return 0;
}

 D 函数

Ax^2+Bx+C;

给系数和区间端点求区间最小最大值

思路:

        1、 A=0 and B=0  f(x)= C minn=maxn =C

        2、 A=0 and B!=0 y= Bx+C  minn = min(f(L),f(R)) maxn=max(f(L),f(R))

        3、 A!=0 and B!=0 

        mid = -(b/2a)

        indx_up = ecil(mid)//向上取整

        indx_d   = floor(mid)//向下取整

        判断 indx_up 、indx_d 是否在区间[L,R]中

        f(indx_up)、f(indx_d)、f(L)、f(R)       

        最小、最大即可

#include <iostream>
#include <cmath>
#define ll long long
using namespace std;

void solve(){
	ll A,B,C,L,R;
	cin>>A>>B>>C>>L>>R;
	if(A==0 && B==0){
		//常数型函数 y=c
		cout<<C<<" "<<C<<"\n";
	}else if(A==0 ){
		//A为0 B不为 0 此时为一元一次函数
		ll aL = A*L*L + B*L +C;
		ll aR = A*R*R + B*R +C;
		ll minn = 1LL*min(aL,aR);
		ll maxn = 1LL*max(aL,aR);
		cout<<minn<<" "<<maxn<<"\n";
	}else{
		//A于B均不为0 即一元二次函数
		double mid = - (B / (2.0*A)) ;//对称轴 //向上取整和向下取整
		ll midu= ceil(mid) , midd = floor(mid);
		//极值点只有三位置可能 俩个端点、对称轴位置
		ll aL = A*L*L + B*L +C;
		ll aR = A*R*R + B*R +C;
		ll amu = A*midu*midu + B*midu +C;
		ll amd = A*midd*midd + B*midd +C;
		
		ll minn = 1LL*min(aL,aR);
		ll maxn = 1LL*max(aL,aR);
		
		if( midu >=L && midu<=R){
			minn = min (minn,amu);
			maxn = max (maxn,amu);
		}
		if(midd >=L && midd <=R){
			minn = min(minn,amd);
			maxn = max(maxn,amd);
		}
		cout<< minn<<" "<<maxn<<"\n";
	}
}
int main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);
	int t;
	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

 E二进制

多推几个样例

发现答案要么是n要么是n+1要么是n+2(大胆的猜结论 )

eg:

11(2)=3

101(2)=5

110(2)=6

1001(2)=9

1010(2)=10

1100(2)=12

1111(2)=15

…………

自此假设n取 [1, 15]

n = 1  

1 X

1+1 √

n= 2

2√

n=3

3 X

4 X

5 √

n=4

4 X

5 √

………… 

#include <iostream>
#include <cmath>
#define ll long long
using namespace std;

bool solve1(int x){
	int cnt=0;
	while(x/2!=0){
		cnt+=x%2;
		x/=2; 
	}
	cnt+=x%2;
	return (cnt%2==0);
}

void solve(){
	int n;
	cin>>n;
	if(solve1(n)){
		cout<<n;
	}else if(solve1(n+1)){
		cout<<n+1;
	}else if(solve1(n+2)){
		cout<<n+2;
	}
	cout<<"\n";
}

int main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);
	int t;
	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

H 修复括号序列 

模拟

(  贡献度 +1 

  )贡献度 -1

需要注意可以修改至多1次

当)优先多于(数量时候必须修改一次 如果修改后仍然出现该情况则 输出NO

如果最后value= 2 (未修改过)那么输出YES

剩下即value = 0 YES

           value  !=0 NO

#include <iostream>
#include <cmath>
#include <cstring>
#define ll long long
using namespace std;


void solve(){
	int n;string temp;
	cin>>n>>temp;
	int cnt=0,x=0;
	for(int i=0;i<n;i++){
		if(temp[i] == '(' )cnt++;
		else if(temp[i] == ')')cnt--;
		if(cnt<0 && x==0){
			x++;
			cnt+=2;
		}else if(cnt<0){
			cout<<"No";
			return;
		}
	}
	if(x==0 && (cnt==0 || cnt==2)){
		cout<<"Yes";
	}else if(cnt==0){
		cout<<"Yes";
	}else{
		cout<<"No";
	}
}

int main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);
	int t=1;
	//cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

 I石子游戏

多推几个样例 找规律

   B B      B B B    
1 2 3 4 5 6 7 8 9 10 11
A       A A           A A A 

会发现 以n方开始长度为n区间内Alice Win 否则 Bob Win n∈N+ 

#include <iostream>
#include <cmath>
#include <cstring>
#define ll long long
using namespace std;


void solve(){
	ll n;
	cin>>n;
	ll a=sqrt(n);
	ll b=a * a +a;
	if( n>=a && n<b){
		cout<<"Alice\n";
	}else{
		cout<<"Bob\n";
	}
}

int main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);
	int t=1;
	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

 J 密码


解释:
条件:
p,q是质数
A*p+B*q=p*q的倍数  <<==>> Ap+Bq=kpq   <<==>>  Ap = kpq - Bq  <<==>>  Ap = (kp-B)q 

根据这个式子Ap = (kp-B)q
可以得到俩个信息 
有可能 p==q
如果p == q
则A = kp -B
A+B = kp
p就是(A+B)的质因子
p的可能个数为(A+B)的质因子个数

如果 p!=q
那么原式改写成
A/q+B/p=k  k∈N+
那么q一定是A的质因子,p一定是B的质因子
组合情况就是A的质因子个数 *B的质因子个数 
但是A的质因子可能与B的质因子个数相同 使得p==q与第一种情况有可能重复了需要减去
假设 Sa是含A的质因子的集合,Sb是含B质因子的集合

result = fac(A)*fac(B); 

假设 存储A质因子元素的集合为Sa、存储B质因子元素的集合为Sb
存储交集元素集合为vis
如果 vis集合中元素未出现(A+B)的质因子元素,且元素个数为x则result需要加上x 

综上所述 
result =  fac(A)*fac(B) + x; 

*/ 

#include <bits/stdc++.h>
#define INT64_MAX	0x7fffffffffffffff
const int N = 1e6 +7;
#define ll long long
using namespace std;

vector<int> prime;//存储质数 
bitset<N>isprime;// 判断i是不是质数 

void euler(int n){
	isprime.set();//全部置1
	isprime[1]=0;
	for(int i=2;i<=n;i++){
		if(isprime[i]){
			prime.push_back(i);
		}
		for(int j=0;j<prime.size() && i*prime[j]<=n;j++){
			isprime[i*prime[j]] = 0;
			if( i% prime[j] == 0){
				break;
			}
		}
	} 
	
}
set<ll> fac(ll x){
	set<ll>s;
	for(int i=0;i<prime.size();i++){
		if(1LL* prime[i]*prime[i]>x){
			break;
		}
		if(x % prime[i] == 0){
			s.insert(prime[i]);
			while(x % prime[i] == 0){
				x/=prime[i];
			}
		}
	}
	if(x>1){
		s.insert(x);
	}
	return s;
}

void solve(){
	ll a,b;
	cin>>a>>b;
	set<ll> faca = fac(a);
	set<ll> facb = fac(b);
	ll res = faca.size() * facb.size();
	set<ll>vis;
	for(set<ll>::iterator it=faca.begin();it!=faca.end();it++){
		if(facb.count(*it)){
			vis.insert(*it);
		}
	}
	set<ll> facab = fac(a+b);
	for(set<ll>::iterator it=facab.begin();it!=facab.end();it++){
		if(!vis.count(*it)){
			res++;
		}
	}
	cout<<res<<"\n";
}

int main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);
	euler(1e6);
	int t=1;
	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

 K 游乐场选址

模板题 

Floyd算法 、枚举所有俩个游乐场的位置求出最小值即可

#include <bits/stdc++.h>
#define INT64_MAX	0x7fffffffffffffff
#define ll long long
using namespace std;

void floyd_warshall(int V, vector<vector<int> >&d){
	for(int k=1;k<=V;k++){
		for(int i=1;i<=V;i++){
			for(int j=1;j<=V;j++){
				d[i][j] = min(d[i][j],d[i][k]+d[k][j]);
			}
		}
	}
}
void solve(){
	int n,m;
	cin>>n>>m;
	vector<vector<int> >g(n+1,vector<int>(n+1,0x3f3f3f3f));
	vector<int>person(n+1); 
	for(int i=1;i<=n;i++){
		cin>>person[i];
		g[i][i]=0;//自己到自己的时间花费为0 
	}
	
	for(int i=1;i<=m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		g[u][v] = min(g[u][v],w);
		g[v][u] = min(g[v][u],w);
	}
	
	floyd_warshall(n,g);
	ll ans = INT64_MAX;
	//枚举
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(i==j)continue;
			ll res=0;
			for(int k=1;k<=n;k++){
				res+= 1LL*(min(g[k][i],g[k][j]))*person[k];
				//cout<<res<<"\n";
			}
			ans = 1LL*min(ans,res);
		}
	} 
	
	cout<<ans <<"\n";
}
int main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);
	int t=1;
//	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chenRenning

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值