ACM题集:https://blog.csdn.net/weixin_39778570/article/details/83187443
题目链接:https://codeforces.com/contest/1100

A

题意:
有两种数,一种1,一种-1,现有一个这两种数组成的数列
从数列里去掉一些数,问剩下1的个数和-1的个数的差的绝对值最大是多少
解:当把1和-1相加就可以表示 1的个数减去-1的个数了
把总和减去去掉的数的和,就表示剩下1的个数和-1的个数的差 
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
int n,k,a[200];
int main(){
	cin>>n>>k;
	int sum=0;
	fo(i,1,n)scanf("%d",&a[i]),sum+=a[i]; 
	// 求和过程相当于 test总数 减 information总数 (因为互为相反数) 
	int ans = 0;
	fo(i,1,k){
		int now = 0;
		for(int j=i; j<=n; j+=k){
			now+=a[j];
		}
		ans = max(ans,(int)fabs(sum-now)); // 做差相当于把关掉的任务去掉 
	}
	cout<<ans<<endl;
	return 0;
}

B

输入k个1~n的数字,当有n个不重复的数字出现时,输出1并把这n个不同数字使用掉,否则输出0,把 
数字存起来

法一:

#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i) 
using namespace std;
int n,k,x,level[100005],cnt[100005]; // level[x]表示第x遍,cnt[x]表示x共有几个 
int main(){
	scanf("%d%d",&n,&k);
	fo(i,1,k){
		scanf("%d",&x);
		if(++level[++cnt[x]]==n)putchar('1');
		else putchar('0');
	}
	return 0;
}

法二:

#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i) 
using namespace std;
int n,k,x;
unordered_map<int,int> mp;
int main(){
	scanf("%d%d",&n,&k);
	fo(i,1,k){
		scanf("%d",&x);
		mp[x]++;
		if(mp.size()>=n){
			fo(j,1,n){
				if(mp.find(j)!=mp.end()){// 查找指针
					mp[j]--;
					if(mp[j]==0)mp.erase(mp.find(j)); 
					// erase(数字)是删掉全部,erase(指针)是删掉一个 
				}
			}
			putchar('1');
		}else putchar('0');
	}
	return 0;
}

C

题意:
给定一个内圆半径R,然后外边有n个圆把内圆无缝包围起来,问内圆半径

解:sin(b)=R/(R+r)===&gt;R=sin(b)r/(1sin(b))sin(b) = R/(R+r) ===&gt;R=sin(b)*r/(1-sin(b))
CF Round #532 (Div. 2)

#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
int n;
double r,ans;
int main(){
	cin>>n>>r;
	double t =sin(3.1415926/n);
	ans = r*t/(1-t);
	printf("%.7f",ans);
	return 0;
}

D

E

题目都看不明白啊~~~
题意是这样的,有一些司机喜欢绕远路多收钱
于是市长就规定不能通过同一个地点两次,他需要反转一些边来实现
就是说要把一幅有环(可能有环)的图通过翻转一些边使得图变无环
反转一些边需要的人员数量不同,人员可以重复使用
也就是说 翻转3条边需要的人员数量为 3 4 5,那么总代价为5 
问最少需要的代价为多少,使得图变为有向无环图,并输出要翻转的边

题解 
最小化问题使用二分查找答案
判断是否是无环图使用拓扑排序,然后根据拓扑排序找出那些构成环的边进行修改 
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
const int maxn = 100005;
struct node{
	int s,t;
	ll cost;
}a[maxn];
int n,m,deg[maxn],top[maxn];
vector<int> G[maxn],ANS;
bool ok(ll mid, bool build){
	fo(i,1,n)G[i].clear();
	memset(deg,0,sizeof(deg));
	
	// 一定要出现的边,不需要翻转 
	fo(i,1,m){
		if(a[i].cost>mid){
			G[a[i].s].push_back(a[i].t);
			deg[a[i].t]++;
		}
	}
	// topsort
	queue<int> q;
	vector<int> tsort; // 清空比较慢(所以不全局了) 
	fo(i,1,n)if(deg[i]==0)q.push(i);
	
	while(!q.empty()){
		int u = q.front();q.pop();
		tsort.push_back(u);
		for(int v:G[u]){
			if(--deg[v]==0){
				q.push(v);
			}
		}
	}
	// 构造答案 
	if(build){		
		fo(i,0,n-1){
			top[tsort[i]]=i; // 点tsort[i]的拓扑序	
		}
		fo(i,1,m){
			if(a[i].cost<=mid && top[a[i].s]>top[a[i].t]){ // top序反了 
				ANS.push_back(i);
			}
		} 
	}
	return tsort.size()==n;
}
void solve(){
	ll L=0,R=1e9,mid,ans=1e9;
	while(L<=R){
		mid = (L+R)>>1;
		if(ok(mid,0)){
			ans = mid;
			R = mid-1;
		}else{
			L = mid+1;
		} 
	}
	ok(ans,1);
	printf("%lld %d\n",ans,ANS.size());
	
	// 这个fo是错的 ANS.size()==0的时候会错 
//	fo(i,0,ANS.size()-1){ // 卧槽,惊了 
//		printf("%d%c",ANS[i],i==ANS.size()-1?'\n':' ');
//	}
	// 这个for是对的 
	for (int i = 0; i < ANS.size(); i++) {
		printf("%d%c",ANS[i],i==ANS.size()-1?'\n':' ');
	}
	
}
vector<int> ver;
int main(){
	cout<<"ver.size() = "<<ver.size()<<endl;
	cout<<"ver.size()-1 = "<<ver.size()-1<<endl;
	
	
	scanf("%d%d",&n,&m);
	fo(i,1,m){
		scanf("%d%d%lld",&a[i].s,&a[i].t,&a[i].cost);
	}
	solve();
	return 0;
} 

相关文章:

  • 2021-05-31
  • 2021-08-19
  • 2021-05-23
  • 2022-01-25
  • 2021-10-21
  • 2021-11-11
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-12-06
  • 2021-11-24
  • 2021-09-04
  • 2021-12-16
  • 2021-11-09
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案