AtCoder Beginner Contest 272题解(不完整)

A - Integer Sum (atcoder.jp)

模拟就好。求数组的和。

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n;
	int ans=0;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int k;
		cin>>k;
		ans+=k;
	}
	cout<<ans<<endl;
	return 0;
 } 

总结:简单模拟题。

B - Everyone is Friends (atcoder.jp)

大致题意就是说能否保证任意两个人都会同时参加至少一个party。存储好和任意一个人同时参加的所有人,然后一个一个的查。

//任意两个人至少参加同一场聚会
#include<bits/stdc++.h>
using namespace std;
set<int>a[110];
int main()
{
	int n,m;
	cin>>n>>m;
	int b[110];
	while(m--)
	{
		int k;
		cin>>k;
		for(int i=1;i<=k;i++)
			cin>>b[i];
		for(int i=1;i<=k;i++)
			for(int j=i+1;j<=k;j++)
			{
				a[b[i]].insert(b[j]);
				a[b[j]].insert(b[i]);
			}
	}
	for(int i=1;i<=n;i++)
		if(a[i].size()<n-1)
		{
			cout<<"No\n";
			return 0;
		}
	cout<<"Yes\n";
	return 0;
} 

总结:仔细一点。

C - Max Even (atcoder.jp)

问是否存在一个偶数是数组当中任意两个数之和,如果存在,求最大的偶数。众所周知,偶数+偶数=偶数,奇数+奇数=偶数,所以说只要存在两个偶数或者是两个奇数就肯定存在答案,再比较最大的两个奇数之和和两个最大偶数之和的最大值,否则就是错的,输出-1.

#include<bits/stdc++.h>
using namespace std;
vector<int>ji;
vector<int>ou;
int main()
{
	int n;
	int a[200010];
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		if(a[i]%2)	ji.push_back(a[i]);
		else	ou.push_back(a[i]);
	}
	sort(ji.begin(),ji.end());
	sort(ou.begin(),ou.end());
	if(ji.size()==1&&ou.size()==1)	cout<<-1<<endl;
	else
	{
		int ans=0;
		if(ji.size()>=2)	ans=ji[ji.size()-1]+ji[ji.size()-2];
		if(ou.size()>=2)	ans=max(ans,ou[ou.size()-1]+ou[ou.size()-2]);
		cout<<ans<<endl;
	}
	return 0;	
} 

总结:简单题,但是在引用的时候要判断一下会不会访问不合法的位置,也就是说判断一下奇数或者是偶数有没有两个再引用。

D - Root M Leaper (atcoder.jp)

最初是在(1,1)的位置上面,每一次移动只能移动到与该点距离的平方为m的位置,问是否能到达所有的位置,要是可以,输出到达所有的位置的最小步数,要是不行,输出-1。对于最短路径,最小步数这种问题,不难想到用bfs,先初始化所有位置的步数为最大值,存储到达所有位置的最小路径,如果说走完之后还有点的步数等于最大值,则输出-1,否则输出这个棋盘。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf 1e9;
#define inf2 2e18;



struct custom_hash {
   static uint64_t splitmix64(uint64_t x) { x += 0x9e3779b97f4a7c15; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; x = (x ^ (x >> 27)) * 0x94d049bb133111eb; return x ^ (x >> 31);}
   size_t operator()(uint64_t x) const { static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count(); return splitmix64(x + FIXED_RANDOM); }
};



struct TrieNode{ TrieNode* child[26]; bool isEnd;
    TrieNode(){ isEnd = false; for(int i = 0; i<26; i++){ child[i] = NULL; } }
};
struct TrieNode* rootTrie;
void addTrie(string& s){ TrieNode* curr = rootTrie; for(int i = 0; i<s.length(); i++){ int n = s[i] - 'a';if(curr->child[n] == NULL){curr->child[n] = new TrieNode();} curr = curr->child[n]; } curr->isEnd = true; }
bool searchTrie(string& s){TrieNode* curr = rootTrie;for(int i = 0; i<s.length(); i++){int n = s[i] - 'a';if(!curr->child[n]) return false;curr = curr->child[n];}return curr->isEnd;}
bool startsWithTrie(string s) {int n = s.length();TrieNode* curr = rootTrie;for(int i  =0 ; i<n; i++){int k = s[i] - 'a';if(curr->child[k] == NULL) return false;curr = curr->child[k];}return true;}



const int MAX_SIZE = 2800001; vector<int>isprime(MAX_SIZE , true); vector<int> idx(MAX_SIZE); vector<int> prime; vector<int>SPF(MAX_SIZE);
void manipulated_seive(int N) {  isprime[0] = isprime[1] = false ; for (int i = 2; i < N ; i++) {  if (isprime[i]) { prime.push_back(i);     SPF[i] = i;  }  for (int j = 0; j < (int)prime.size() && i * prime[j] < N && prime[j] <= SPF[i]; j++) {  isprime[i * prime[j]] = false;   SPF[i * prime[j]] = prime[j] ; }  }   for (int i = 0; i < (int)prime.size(); i++) { idx[prime[i]] = i + 1; }}
vector<ll> primeFactors(ll n) { vector<ll> factors; while (n > 1) { factors.push_back(SPF[n]); n /= SPF[n]; } return factors;}
void precision(int dp) {cout << setprecision(dp) << fixed;}
ll gcd(ll dp, ll b) {return (b == 0 ? dp : gcd(b, dp % b));}
ll lcm(ll dp, ll b){return (dp / gcd(dp, b)) * b;}
string convertNtoB(int n){ string ans = ""; int binaryNum[32]; int i = 0; while (n > 0) { binaryNum[i] = n % 2; n = n / 2; i++; } for (int j = i - 1; j >= 0; j--) ans+=to_string(binaryNum[j]); return ans; }
int convertBtoN(string n){ string num = n; int dec_value = 0; int base = 1; int len = num.length(); for (int i = len - 1; i >= 0; i--) { if (num[i] == '1') dec_value += base; base = base * 2; } return dec_value; }
vector<int> numberToBinary(long long int n) { vector<int> v; long long int quo, rem; while(n/2) { quo = n/2; rem = n - (2 * quo); v.push_back(rem); n /= 2; } v.push_back(1); reverse(v.begin(), v.end()); return v; }


int n, m, dp[500][500];

vector<int> dx, dy;
queue<pair<int,int>>q;

bool check(int x, int y) {
	if(x<0 or x>=n or y<0 or y>=n) return true;
    return false;
}
void bfs() {
	q.push({0, 0});
	while(!q.empty()) {
		int x = q.front().first, y = q.front().second;
		q.pop();
		for (int i = 0; i < dx.size(); i++) {
			int cntx = x+dx[i];
            int cnty = y+dy[i];
			if(check(cntx, cnty)) continue;
			if(dp[cntx][cnty] != -1) {
                continue;
            }
			dp[cntx][cnty] = dp[x][y] + 1;
			q.push({cntx, cnty});
		}
	}
}


void solve(){
	cin>>n>>m;
    memset(dp, -1, sizeof(dp));
	for (int i = -1000; i <= 1000; i++){
        for (int j = - 1000; j <= 1000; j++){
            if(i * i + j * j == m){
                dx.push_back(i);
                dy.push_back(j);
            }
        }
    }
	dp[0][0] = 0;
	bfs();
	for(int i = 0; i<n; i++){
        for(int j = 0; j<n; j++){
            cout<<dp[i][j]<<" ";
        }
        cout<<endl;
    }
}



int main(){
//Jai Shree Ram
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    
    int t = 1;
    while(t--){ solve();}
        
        
    return 0;
}

总结:求开个号难求,可以现预处理出所有能走的路径,减少后续操作。想问题要全面一些,考虑到所有能走的方法。

E - Add and Mex (atcoder.jp)

有m次操作,每一次操作可以使得a [ i ] + = i .问每一次操作之后在数组当中没有出现的最小非负数。其实有用的数字只有0 < =x<=n,小于0的数以及大于等于n的数可以直接舍弃掉,对于每一个数,存储在他可能会有用的set里面,在一个一个查,从0开始查,只要数组里面没有,就直接输出并且break掉。

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
set<int>f[N]; 
int a[N];
int main()
{
	//每一轮的数都要在1<=a[i]<=n的范围之内,小于0和大于n的数可以直接舍弃掉,将每一轮可能会有的数存储起来
	//调和级数:nlogn 
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		int cnt=0;
		if(a[i]<0)
		{
			int cha=-a[i];
			cnt+=cha/i;
			a[i]+=cnt*i;
		}
		while(a[i]<=n&&cnt<=m)
		{
		//	if(a[i]>=0)
			f[cnt].insert(a[i]);
			a[i]+=i;
			cnt++;
		}
	}
//	int cnt=1;
	for(int cnt=1;cnt<=m;cnt++)
	{
		for(int i=0;i<=n;i++)
			if(!f[cnt].count(i))
			{
				cout<<i<<endl;
				break;
			}
		//cnt++;
	}
	//for(int i=n+1;i<=m;i++)
	return 0;	
}

总结:尽量去减少时间复杂度,对于负数,在前面的操作根本就没有贡献,那就O(1)直接跳过,减少不必要的时间复杂度。另外,调和级数的时间复杂度:O(nlogn).

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值