Codeforces Round #615 (Div. 3)(完结)

A - Collecting Coins
题意:给你四个数a,b,c,n;让你把n给个a,b,c三个数使a,b,c相等且n恰好分完
思路:找出a,b,c中最大的先将其他两个加到最大的,然后判断剩下的n是否能被3整除即可;

#include<bits/stdc++.h>
#define accept return 0
#define  mes(a, b)  memset(a, b, sizeof a)
typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 2e5 + 5;
const int    maxm = 1e5 + 10;
const int    mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-6;
using namespace std;
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		int a[3],n;
		for(int i = 0;i < 3;i++) cin >> a[i];
		sort(a,a + 3);
		int cha = a[2] - a[0] + a[2] - a[1];
		cin >> n;
		if(cha > n) puts("NO");
		else if((n - cha)%3) puts("NO"); 
		else puts("YES");
	}
}

B - Collecting Packages
题意:给你n个点,让只能往上或者往右走,不能回头,让你判断能不能走完所有的点,如果能走完输出走的路径。
思路:按x排序,x相同按y排序,依次走过这几个点即可。

#include<bits/stdc++.h>
#define accept return 0
#define  mes(a, b)  memset(a, b, sizeof a)
typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 2e5 + 5;
const int    maxm = 1e5 + 10;
const int    mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-6;
using namespace std;
struct node{
	int x,y;
	bool operator <(const node &a)const{
		if(x == a.x) return y < a.y;
		return x < a.x;
	}
}a[maxn];
string s;
int main(){
	int T;cin >> T;
	while(T--){
		int n;cin >> n;
		for(int i = 1;i <= n;i++) cin >> a[i].x >> a[i].y;
		sort(a + 1,a + 1 + n);
		s.clear();
		int sx = 0,sy = 0;
		int flag = 0;
		for(int i = 1;i <= n;i++){
			while(a[i].x > sx) sx++,s += 'R';
			if(a[i].y < sy){
				flag = 1;break;
			}
			while(a[i].y > sy) sy++,s += 'U';
		}
		if(flag == 1)puts("NO");
		else {
			puts("YES");cout << s <<"\n"; 	
		}
	}
}

C - Product of Three Numbers
题意:给你一个数n,让你分解成三个不同的数的乘积形式,若不能输出no。
思路:考虑分解出两个数,然后用除法求出第三个数判断是否与前两个数相同即可。

#include<bits/stdc++.h>
#define accept return 0
#define  mes(a, b)  memset(a, b, sizeof a)
typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 2e5 + 5;
const int    maxm = 1e5 + 10;
const int    mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-6;
using namespace std;
vector<int>ans;
int main(){
	int T;cin >> T;
	while(T--){
		ans.clear();
		int n;cin >> n;
		int num = 0;
		for(int i = 2;i * i <= n;i++){
			if(n % i == 0) n /= i,ans.push_back(i),num++;
			if(num == 2) break;
		}
		if(num < 2) printf("NO\n");
		else if(ans[0] != n && ans[1] != n) puts("YES"),printf("%d %d %d\n",ans[0],ans[1],n);
		else printf("NO\n");
	}
}

D - MEX maximizing
题意:给你q次操作,x为每层的个数。每次操作在集合中加入一个数n,你可以对n进行任意次+n或-n操作,问这个集合中不存在的最小的整数是多少。
思路:

以下提供两种思路:
1:
用线段树维护我最多可以凑出多少层,线段树查询第一个不满足该层的是哪个即为ans,答案就是 层数*x+ans-1;

#include<bits/stdc++.h>
#define accept return 0
#define  mes(a, b)  memset(a, b, sizeof a)
typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 4e5 + 5;
const int    maxm = 1e5 + 10;
const int    mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-6;
using namespace std;
int a[maxn << 2];
void update(int rt,int l,int r,int s){
	if(l == r) {
		a[rt]++;return;
	}
	int mid = l + r >> 1;
	if(s <= mid) update(rt << 1,l,mid,s);
	else update(rt<< 1 | 1,mid + 1,r, s);
	a[rt] = min(a[rt << 1],a[rt << 1 | 1]);
}
int query(int rt,int l,int r,int sum){
	if(l == r) return l;
	int mid = l + r >> 1;
	if(a[rt << 1] == sum) return query(rt << 1,l,mid ,sum);
	else return query(rt << 1 | 1,mid + 1,r,sum);
}
int main(){
	int x,q;cin >> q >> x;
	while(q--){
		int n;cin >> n;
		update(1,1,x,n % x + 1);
		int ans = query(1,1,x,a[1]);
		cout << a[1] * x + ans - 1 << "\n";
	}
}

2:
我们只需要保存集合中%x为0 ~ x-1的个数,用一个tmp去记录答案。当你的a[tmp%x]不为0的时候,你的tmp就可以++,同时就说明你这个a[tmp%x]已经被用掉一个了,就需要减去一个了。

#include<bits/stdc++.h>
#define accept return 0
#define  mes(a, b)  memset(a, b, sizeof a)
typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 4e5 + 5;
const int    maxm = 1e5 + 10;
const int    mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-6;
using namespace std;
int has[maxn];
int main(){
	int q,x;cin >> q >> x;
	int ans = 0; 
	while(q--){
		int n;scanf("%d",&n);
		has[n % x]++;	
		while(has[ans % x]){
			has[ans % x]--;
			ans++;
		}
		printf("%d\n",ans);
	}
}

E - Obtain a Permutation
题意:给你一个n*m的矩阵,你可以进行两个操作:
1:对一列向上一个单位,第一个放到最后一个。
2:改变某个位置上数的值。
问你需要操作几次才能使矩阵按照顺序排列好。
思路:
首先它具有独立性,我不会和行有关,只会与列相关。于是我们就按列去考虑。考虑暴力的方法,我们用一个cnt数组去记录该数要以列第几个数作为第一行时不需要以动。然后对于第i个数作为开头的花费就是n - cnt[i] + i;对i进行遍历就可以求出每行的最小花费即可。

#include<bits/stdc++.h>
#define accept return 0
#define  mes(a, b)  memset(a, b, sizeof a)
typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 2e5 + 5;
const int    maxm = 1e5 + 10;
const int    mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-6;
using namespace std;
int ans = 0;
int main(){
  	int n, m;
  	cin >> n >> m;
  	vector<vector<int>> a(n, vector<int>(m));
  	for (int i = 0; i < n; i++){ 
    	for (int j = 0; j < m; j++) {
      		cin >> a[i][j];
      		a[i][j]--;
   	 	}
	}
	for(int j = 0;j < m;j++){
		vector<int>cnt(n);
		for(int i = 0;i < n;i++){
			if(a[i][j] % m == j && a[i][j] < m * n){
				cnt[(i - a[i][j] / m + n) % n]++;
			}
		}
		int minn = n;
		for(int i = 0;i < n;i++){
			minn = min(minn,n - cnt[i] + i);
		}
		ans += minn;
	}
	cout << ans << endl;
}

F. Three Paths on a Tree
题意:表述很简单,给你一颗树,让你找出3个点使这三个任意两点相连覆盖的点的并集最大。
思路:首先这三个点必有两个点是树的直径,直径的求法为随便找一个点bfs到最远的为直径的一个端点。用这个端点再bfs出来的最远的点即为圆的另一个端点。我们在bfs的同时也可以把这两个端点到每个其他点的距离也处理出来,然后我们对n个点(出去两个端点)进行遍历,答案为(树的直径+该点到两个端点的距离)/ 2,然后求最大值输出即可。

#include<bits/stdc++.h>
#define accept return 0
#define  mes(a, b)  memset(a, b, sizeof a)
typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 2e5 + 5;
const int    maxm = 1e5 + 10;
const int    mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-6;
using namespace std;
int pos;
vector<int>mp[maxn];
int dis1[maxn],dis2[maxn],dis[maxn],vis[maxn];
void bfs(int x){
	mes(vis,0);mes(dis,0);
	pos = x;vis[x] = 1;dis[x] = 0;
	queue<int>q;q.push(x);
	while(!q.empty()){
		int u = q.front();q.pop();
		for(auto it : mp[u]){
			if(vis[it]) continue;
			vis[it] = 1;
			dis[it] = dis[u] + 1;
			q.push(it);
			if(dis[it] > dis[pos]) pos = it;
		}
	}
	
}
int main(){
	int n;scanf("%d",&n);
	for(int i = 1;i < n;i++){
		int u,v;scanf("%d %d",&u,&v);
		mp[u].push_back(v);mp[v].push_back(u);
	}	
	int a,b,c;
	bfs(1);a = pos;
	bfs(pos);b = pos;
	for(int i = 1;i <= n;i++) dis1[i] = dis[i];
	bfs(pos);
	for(int i = 1;i <= n;i++) dis2[i] = dis[i];
	c = 0;
	for(int i = 1;i <= n;i++){
		if(dis1[i] + dis2[i] > dis1[c] + dis2[c] && i != a && i != b) c = i;
	}
	printf("%d\n%d %d %d\n",(dis2[a] + dis1[c] + dis2[c]) / 2,a,b,c);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
协同过滤算法(Collaborative Filtering)是一种经典的推荐算法,其基本原理是“协同大家的反馈、评价和意见,一起对海量的信息进行过滤,从中筛选出用户可能感兴趣的信息”。它主要依赖于用户和物品之间的行为关系进行推荐。 协同过滤算法主要分为两类: 基于物品的协同过滤算法:给用户推荐与他之前喜欢的物品相似的物品。 基于用户的协同过滤算法:给用户推荐与他兴趣相似的用户喜欢的物品。 协同过滤算法的优点包括: 无需事先对商品或用户进行分类或标注,适用于各种类型的数据。 算法简单易懂,容易实现和部署。 推荐结果准确性较高,能够为用户提供个性化的推荐服务。 然而,协同过滤算法也存在一些缺点: 对数据量和数据质量要求较高,需要大量的历史数据和较高的数据质量。 容易受到“冷启动”问题的影响,即对新用户或新商品的推荐效果较差。 存在“同质化”问题,即推荐结果容易出现重复或相似的情况。 协同过滤算法在多个场景中有广泛的应用,如电商推荐系统、社交网络推荐和视频推荐系统等。在这些场景中,协同过滤算法可以根据用户的历史行为数据,推荐与用户兴趣相似的商品、用户或内容,从而提高用户的购买转化率、活跃度和社交体验。 未来,协同过滤算法的发展方向可能是结合其他推荐算法形成混合推荐系统,以充分发挥各算法的优势。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值