Daliy Algorithm (GPLT)-- day 95
Nothing to fear
种一棵树最好的时间是十年前,其次是现在!
那些你早出晚归付出的刻苦努力,你不想训练,当你觉的太累了但还是要咬牙坚持的时候,那就是在追逐梦想,不要在意终点有什么,要享受路途的过程,或许你不能成就梦想,但一定会有更伟大的事情随之而来。 mamba out~
2020.7.8-7.10
人一我十,人十我百,追逐青春的梦想,怀着自信的心,永不言弃!
1370C - Number Game
分析
有如下三种情况F会赢 , 其余得情况都是A会赢
- 1.当 n = 1得时候,此时A无法进行任何操作。但是当n = 其余奇数得时候一定是 A会赢
- 2.n是偶数并且其不存在奇数得因子,即当 n 为 \(2 ^x(x > 1)\)次幂时此时A只能选择-1, F一定会赢
- 3.当 n 是偶数,并且具有奇数因子。如果n = \(2^x * p (x > 1)\) 那么此时A让n 变为 n / p,A一定会赢,否则n 必须是 n = 2 * p得形式,且p一定是奇数,如果p是一个质数,此时A只能减少1
#include <bits/stdc++.h>
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define lowbit(x) (x & -x)
using namespace std;
typedef long long ll;
const int MAX = 0x7ffffff;
int t;
bool check_prime(int x)
{
for(int i = 2;i <= sqrt(x);i ++)
{
if(x % i == 0)return false;
}
return true;
}
void slove()
{
int n;
cin >> n;
bool lose = (n == 1);
if(n > 2 && n % 2 == 0)
{
if((n & (n - 1)) == 0)
lose = 1;
else if(n % 4 != 0 && check_prime(n / 2))
lose = 1;
}
if(lose)printf("FastestFinger\n");
else printf("Ashishgup\n");
}
int main()
{
#ifdef LOCAL
auto start_time = clock();
cerr << setprecision(3) << fixed; // 在iomanip中
#endif
SIS;
cin >> t;
while(t--)
{
slove();
}
#ifdef LOCAL
auto end_time = clock();
cerr << "Execution time: " << (end_time - start_time) * (int)1e3 / CLOCKS_PER_SEC << " ms\n";
#endif
}
GPLT - L2-026 小字辈
考点 深度优先,广度优先搜索
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 100005;
int n , root;
vector<int> a[N];
vector<int> ans;
int depth;
bool vis[N];
void dfs(int now , int level)
{
if(depth < level)
{
ans.clear();
depth = level;
}
if(level == depth){
ans.push_back(now);
}
for(int i = 0;i < a[now].size() ;i ++)
{
if(!vis[a[now][i]])
{
vis[a[now][i]] = 1;
dfs(a[now][i] , level + 1);
vis[a[now][i]] = 0;
}
}
}
int main()
{
cin >> n;
int x;
for(int i = 1;i <= n;i ++)
{
scanf("%d",&x);
if(x == -1)
{
root = i;
continue;
}
a[x].push_back(i);
}
dfs(root , 1);
cout << depth << endl;
sort(ans.begin(),ans.end());
for(int i = 0;i < ans.size(); i++)
{
if(i == 0)printf("%d",ans[i]);
else printf(" %d",ans[i]);
}
return 0;
}
GPLT - L2-027 名人堂与代金券
注意排rank有一些小坑
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
using namespace std;
const int N = 100005;
struct node{
string who;
int score = -1;
}a[N];
int n , g , k;
int d50, d20;
bool cmp(node a,node b)
{
if(a.score == b.score)
{
return a.who < b.who;
}else return a.score > b.score;
}
int main()
{
cin >> n >> g >> k;
for(int i = 0;i < n ;i ++)
{
cin >> a[i].who >> a[i].score;
if(a[i].score >= g && a[i].score <= 100)d50++;
if(a[i].score >= 60 && a[i].score < g)d20++;
}
sort(a , a + n , cmp);
cout << d50 * 50 + d20 * 20 << endl;
int id = 0, rank = 1 , pre = a[0].score;
while(rank <= k)
{
int cnt = 0;
while(a[id].score == pre)
{
cout << rank << " " << a[id].who << " " << a[id].score << endl;
id++;cnt++;
}
rank += cnt, pre = a[id].score;
}
return 0;
}
GPLT - L2-029 特立独行的幸福
真就大模拟呗没啥说的
自己分析得过程
- 特立独行就是从自己开始不依赖于任何其他得数字
- 如果一个数字经历若干次迭代之后遇到了死循环则这个数一定不是幸福数
- 它的独立性是指从自己开始经过多少次会变为每一位得平方和加起来等于1
- 如果这个数是素数则独立性还需要乘2
- 对于依附于初始数字得数不是独立得幸福数需要被标记
需要用到得数据结构:
- 判断这个数是否已经被标记为不是幸福 : isxingFu
判断这个数字是否是个衣服于其他数字得幸福数 - 需要一个数据结构存放当前这一个数字往下传递所产生得数字
- 如果这个数字是独立得幸福数,记录其独立性
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
int l , r;
const int N = 1000005;
int ans[N];
bool isxingFu[N], isyilai[N];
bool isprime(int n)
{
for(int i = 2;i <= sqrt(n) ;i ++)
{
if(n % i == 0)return 0;
}
return 1;
}
int getsum(int x)
{
int ans = 0;
while(x)
{
int t = x % 10;
ans += t*t;x /= 10;
}
return ans;
}
bool find(int x ,vector<int> &v)
{
for(int i = 0;i < v.size(); i++)
{
if(x == v[i])return true;
}
return false;
}
bool check(int n)
{
vector<int> v;
int now = n;
while(1)
{
if(find(now , v))
{
isxingFu[n] = false;
return false;
}
v.push_back(now);
int next = getsum(now);
if(next == 1)//说明 n 是幸福数 计算其幸福度
{
isxingFu[n] = 1;
if(isprime(n))
{
ans[n] = v.size() * 2;
}else ans[n] = v.size();
// 把从第1位开始得数字标记为依赖
for(int i = 1;i < v.size();i ++)
{
isyilai[v[i]] = 1;
}
return true;
}
now = next;
}
}
int main()
{
cin >> l >> r;
int cnt = 0;
for(int i = l;i <= r;i ++)
{
check(i);
}
for(int i = l;i <= r;i ++)
{
if(ans[i] > 0 && !isyilai[i] && isxingFu[i])
{
printf("%d %d\n", i ,ans[i]);
cnt++;
}
}
if(cnt == 0)printf("SAD\n");
return 0;
}
GPLT - L2-031 深入虎穴
分析
实际是求一棵树的最大深度的结点的id而已,只需要设计一下结点之中带上父节点的信息,然后遍历 1 - n结点找到哪个根节点进行遍历即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 100005;
struct node{
int fa = -1;
vector<int> son;
}v[N];
int n , maxlen = -1, maxid = -1;
void dfs(int now , int level)
{
if(level > maxlen){
maxlen = level;
maxid = now;
}
for(int i = 0;i < v[now].son.size();i ++)
{
int next = v[now].son[i];
dfs(next , level + 1);
}
}
int main()
{
cin >> n;
for(int i = 1;i <= n;i ++)
{
int k , x;cin >> k;
for(int j = 0;j < k;j ++)
{
scanf("%d",&x);
v[i].son.push_back(x);
v[x].fa = i;
}
}
for(int i = 1;i <= n ;i ++)
{
if(v[i].fa == -1)
{
dfs(i , 0);
cout << maxid << endl;
break;
}
}
return 0;
}
GPLT - L2-032 彩虹瓶
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <stack>
using namespace std;
const int N = 1005;
int n , m, k;
void slove()
{
stack<int> s;
int index = 1 , t , flag = 0;
for(int i = 0;i < n;i ++)
{
cin >> t;
if(t == index){
index++;
while(!s.empty() && s.top() == index){
s.pop();index++;
}
}else{
if(t > index)s.push(t);
if(s.size() > m)flag = 1;
}
//printStack(s);
}
if(s.size() == 0 && flag == 0)cout << "YES" << endl;
else cout << "NO" << endl;
}
int main()
{
cin >> n >> m >> k;
while(k--)slove();
return 0;
}
GPLT - L2-028 秀恩爱分得快
分析
- 首先性别需要用字符串来表示不然没办法判断为0的情况
- 存储方式,如果将每两个人都进行判断的话肯定会超时
所以需要找一个容器先将他们暂时存起来- 为了节省时间首先应该检查是否存在A , B 如果存在单独对A / B进行附加权值否则就跳过
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
using namespace std;
const int N = 100005;
bool sex[N]; // sex = 1 表示男性 ,sex = 0 表示女性
int n , m ;
string A , B;
struct node{
string val;
int id;
};
double rea[N], reb[N];
vector<node> ansA, ansB;
vector<int> box[N];
bool cmp(node a, node b)
{
if(a.val == b.val)
{
return a.id < b.id;
}else return a.val > b.val;
}
void output()
{
string pre = ansA[0].val;
for(int i = 0;i < ansA.size() ;i++){
if(ansA[i].val == pre)
cout << A,
printf("%s%d\n",(sex[ansA[i].id] == 0 ? " -" : " ") ,ansA[i].id);
}
pre = ansB[0].val;
for(int i = 0;i < ansB.size();i ++){
if(ansB[i].val == pre)
cout << B,
printf("%s%d\n",(sex[ansB[i].id] == 0 ? " -" : " ") ,ansB[i].id);
}
}
bool find(vector<node> v,int id)
{
string pre = v[0].val;
for(int i = 0;i < v.size() ;i ++)
{
if(pre == v[i].val && id == v[i].id)
return true;
}
return false;
}
int main()
{
cin >> n >> m;
for(int i = 0;i < m;i ++)
{
int k;cin >> k;
for(int j = 0;j < k;j ++)
{
string s;cin >> s;
int tmp = abs(stoi(s));
if(s == "0")sex[0] = 1;
else if(s == "-0")sex[0] = 0;
else sex[tmp] = !(s[0] == '-');
box[i].push_back(tmp);
}
}
cin >> A >> B;
int a = abs(stoi(A)) , b = abs(stoi(B));
for(int i = 0;i < m; i++)
{
bool fa = 0 , fb = 0;
for(int j = 0;j < box[i].size();j ++)
{
if(box[i][j] == a)fa = 1;
if(box[i][j] == b)fb = 1;
}
int k = box[i].size();
if(fa || fb){
for(int j = 0;j < k;j ++)
{
int id = abs(box[i][j]);
if(fa)rea[id] += 1.0 / k;
if(fb)reb[id] += 1.0 / k;
}
}
}
for(int i = 0;i < n;i ++)
{
if(sex[a] != sex[i]){
ansA.push_back({to_string(rea[i]) , i});
}
if(sex[b] != sex[i]){
ansB.push_back({to_string(reb[i]) , i});
}
}
sort(ansA.begin(), ansA.end(), cmp);
sort(ansB.begin(), ansB.end(), cmp);
bool f1 = find(ansA , b), f2 = find(ansB , a);
if(f1 && f2)
{
cout << A << " " << B;
return 0;
}else output();
return 0;
}
GPLT - L2-030 冰岛人
五服之内不能通婚,是指的是“五代以内无公共祖先”是指两人的公共祖先(如果存在的话)必须比任何一方的曾祖父辈分高。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdio>
#include <unordered_map>
#include <string>
#include <queue>
#include <map>
#include <cstring>
using namespace std;
const int N = 100005;
map<string ,int> Ming;
vector<pair<string,string>> v;
int key = 2, n;
struct node{
int sex = 1, fa = -1; // 1 表示男性
}P[N];
bool vis[N];
void buildTree()
{
string f , s;
for(int i = 0;i < n;i ++)
{
f = v[i].first , s = v[i].second;
int l = s.size();string name;
if(s[l - 1] != 'r' && s[l - 1] != 'n')continue;
if(P[Ming[f]].sex)
name = s.substr(0 , l - 4);
else name = s.substr(0 , l - 7);
P[Ming[f]].fa = Ming[name];
}
}
void inputandmap()
{
cin >> n;
string f , s; // f是名字 , s是姓
for(int i = 0;i < n ;i ++)
{
cin >> f >> s;
v.push_back({f , s});
Ming[f] = key;
int l = s.size();
if(s[l - 1] == 'm' || s[l - 1] == 'n')
P[key].sex = 1;
else P[key].sex = 0;
key++;
}
}
bool check(int a,int b)
{
memset(vis , 0 , sizeof vis);
int level = 1;
int disA[N] = {0} , disB[N] = {0};
for(int i = a , cnt = 0;i != -1;i = P[i].fa,cnt++){
disA[i] = cnt;
vis[i] = 1;
}
level = 1;
for(int i = b , cnt = 0;i != -1;i = P[i].fa,cnt++)
{
disB[i] = cnt;
if(vis[i])
{
if(disA[i] >= 4 && disB[i] >= 4)
return true;
else return false;
}
}
return true;
}
int main()
{
inputandmap();
buildTree();
int m;cin >> m;
string fa , sa , fb , sb;
for(int i = 0;i < m;i ++)
{
cin >> fa >> sa >> fb >> sb;
if(Ming.find(fa) == Ming.end() || Ming.find(fb) == Ming.end() )
{
cout << "NA" << endl;
continue;
}
if(P[Ming[fa]].sex == P[Ming[fb]].sex){
cout << "Whatever\n";
continue;
}
if(check(Ming[fa] , Ming[fb]))
{
cout << "Yes" << endl;
}else cout << "No" << endl;
}
return 0;
}