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).