Codeforces Round #665 (Div. 2) A~D

A:
特判情况,当n是<=k 的时候,都可以把让B为0点,A为n点。
否则:
当k时奇数的时候,AB,OB的距离差会构成全为奇数的长度。
反之为偶数。

#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<iostream>
#include<algorithm>
#define int long long
#define sc scanf
#define pf printf
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned long long LL;
 
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const int mod = 9901;
const int N = 1010;
 
signed main(){
	IOS;
	#ifdef ddgo
		freopen("C:/Users/asus/Desktop/ddgoin.txt","r",stdin);
	#endif
	
	int tt; cin>>tt;
	while(tt --){
		int n,k; cin>>n>>k;
		if(n <= k) cout<<k-n<<endl;
		else{
			if(k%2){
				if(n%2) cout<<0<<endl;
				else cout<<1<<endl;
			}else{
				if(n%2 == 0) cout<<0<<endl;
				else cout<<1<<endl;
			}
		}
	}
	
	return 0;
}

B:
a里面当2对应b里面1是会增加,当b里面2对应a里面1会减少。其他情况都为0.
所以我们只需要计算
a里面有多少2对应1 ,2多了和b里面2抵消。
b里面有多少2对应1.

代码:

#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<iostream>
#include<algorithm>
#define int long long
#define sc scanf
#define pf printf
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned long long LL;
 
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const int mod = 9901;
const int N = 1010;
 
signed main(){
	IOS;
	#ifdef ddgo
		freopen("C:/Users/asus/Desktop/ddgoin.txt","r",stdin);
	#endif
	
	int tt; cin>>tt;
	while(tt --){
		int a,b,c,a1,b1,c1; cin>>a>>b>>c>>a1>>b1>>c1;
		int sum = 2*min(c,b1)-2*min(b,max(0ll,c1-a-max(0ll,c-b1)));
		cout<<sum<<endl;
	}
	
	return 0;
}

C:
当某个数能被min整除时,说明它可以与min交换,那么我们可以利用这一点,把所有的能和min交换的数都交换。
我们只需判断当一个数不能整除min时,它若不处于本该处于的位置,则得不到合法序列。若所有这些情况都满足,则剩余的每一个位置,都可以通过与min交换得到合法序列。

代码:

#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<iostream>
#include<algorithm>
#define int long long
#define sc scanf
#define pf printf
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned long long LL;
 
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const int mod = 9901;
const int N = 100010;
 
int a[N],b[N];
 
signed main(){
//	IOS;
	#ifdef ddgo
		freopen("C:/Users/asus/Desktop/ddgoin.txt","r",stdin);
	#endif
	
	int tt; cin>>tt;
	while(tt --){
		int n,mi = INF; cin>>n;
		for(int i=0;i<n;i++){
			cin>>a[i],b[i] = a[i];
			mi = min(mi,a[i]);
		}
		bool plas = true;
		sort(b,b+n);
		for(int i=0;i<n;i++){
			if(a[i] % mi != 0 && a[i] != b[i]){
				plas = false;
				break;
			} 
		}
		cout<<(plas?"YES":"NO")<<endl;
	}
	return 0;
}

D:
此题贪心一下,想得到最大值,必然让走过最多次数的边的权值最大。
走过边的次数为,那条边左端点子树的数量乘右端点子树的数量(包括端点)。
这里可以用dfs的方法求出来。最后p和求出来的次数一一对应就可以了。

注意: 题上并没有说m<n.所以会分两种情况处理p数组,一种是让某些p为1.
种是让p等于它后面几个的连乘。

#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<iostream>
#include<algorithm>
#include<cstring>
#define int long long
#define sc scanf
#define pf printf
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned long long LL;
 
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const int mod = 1e9+7;
const int N = 200010;
 
int e[N],ne[N],h[N],idx=1;
 
void add(int a,int b){
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
 
int si[N],cnt,p[N],a[N],n,m;
int dfs(int u,int fa){
	si[u] = 1;
	for(int i=h[u];i;i=ne[i]){
		int j = e[i];
		if(j == fa) continue;
		si[u] += dfs(j,u);
		a[++cnt] = si[j] * (n-si[j]);
	}
	return si[u];
} 
 
void init(){
	memset(h,0,sizeof(h));
	idx = 1;
	cnt = 0;
}
 
signed main(){
//	IOS;
	#ifdef ddgo
		freopen("C:/Users/asus/Desktop/ddgoin.txt","r",stdin);
	#endif
	
	int tt; cin>>tt;
	while(tt --){
		init();
		cin>>n;
		for(int i=0;i<n-1;i++){
			int a,b; cin>>a>>b;
			add(a,b);add(b,a);
		}
		dfs(1,0);
		cin>>m;
		for(int i=1;i<=m;i++) cin>>p[i];
		for(int i=m+1;i<=n-1;i++) p[i] = 1;//p处理,下面第一个sort也与这个有关
		sort(p+1,p+max(m+1,n)); sort(a+1,a+cnt+1);
		while(m-- > cnt) p[m] = (p[m] * p[m+1]) % mod;//p处理
		int sum = 0;
		for(int i=1;i<=cnt;i++)
			sum = (sum + (p[i] * a[i])%mod) % mod;
		cout<<sum<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值