B. Breaking Branches
没人选一次会让n减一,所以n奇数先手必败,偶数先手必胜
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
*/
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n;
if(n%2==0)
{
cout<<"Alice"<<endl;
cout<<1<<endl;
}
else
{
cout<<"Bob"<<endl;
}
return 0;
}
J. Jazz it Up!
给n,让你找出m,m*n不是平方数的倍数。
找出n的质因子,m为不是n的质因子的质数。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
*/
map<ll,ll>mp;
int vs[M];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
ll n;
cin>>n;
for(int i=2;i<=n;i++)if(n%i==0)mp[i]=1;
for(int i=2;i<=n;i++)
{
if(vs[i])continue;
for(int j=i+i;j<=n;j+=i)
vs[j]=1;
}
for(int i=2;i<=n;i++)
{
if(vs[i]==0&&mp[i]==0)
{
cout<<i<<endl;
return 0;
}
}
return 0;
}
H. Historic Exhibition
一个明显的贪心:底座直径相同,尽量用。
然后按底座最小的直径进行排序。
优先安排小的,因为后面的至少不会小与这个小的。
模拟下就行
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e4+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
*/
struct node{
int x,y,id;
}p[M];
int mp[M],a[M];
bool cmp(node a,node b)
{
return a.x<b.x;
}
int main()
{
int n,m,x,y,sz=0,ct=0;
cin>>n>>m;
vector<int>v[M];
for(int i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
if(x>y)swap(x,y);
p[i]=node{x,y,i};
}
for(int i=1;i<=m;i++)scanf("%d",&a[i]),mp[a[i]]++;
for(int i=1;i<=n;i++)
{
if(p[i].x==p[i].y)
{
x=p[i].x;
if(mp[x])
v[x].pb(i),mp[x]--,ct++;
}
else p[++sz]=p[i];
}
sort(p+1,p+1+sz,cmp);
for(int i=1;i<=sz;i++)
{
x=p[i].x,y=p[i].y;
if(mp[x])v[x].pb(p[i].id),mp[x]--,ct++;
else
{
if(mp[y])
v[y].pb(p[i].id),mp[y]--,ct++;
}
}
bool f=true;
if(ct==m&&m&&n)
{
for(int i=1;i<=m;i++)
{
int l=v[a[i]].size();
// cout<<a[i]<<"------------"<<l<<endl;
printf("%d\n",v[a[i]][l-1]);
v[a[i]].pop_back();
}
}
else
cout<<"impossible"<<endl;
return 0;
}
F. Find my Family
set维护下,前面的大于当前数的最小值,再看后面有没有大于这个值的数。
有就可以
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 3e5+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
*/
int a[M],mx[M];
set<int>s;
int main()
{
int K;
cin>>K;
vector<int>v;
for(int k=1;k<=K;k++)
{
int n;
cin>>n;
bool f=false;
s.clear();
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
mx[n+1]=0;
for(int i=n;i>=1;i--)mx[i]=max(a[i],mx[i+1]);
for(int i=1;i<=n;i++)
{
auto it=s.upper_bound(a[i]);
// cout<<i<<" "<<*it<<" "<<mx[i+1]<<endl;
if(it!=s.end()&&(*it<mx[i+1]))f=true;
s.insert(a[i]);
}
if(f)v.pb(k);
}
printf("%d\n",v.size());
for(int i=0;i<v.size();i++)
printf("%d\n",v[i]);
return 0;
}
E. Efficient Exchange
从高到低考虑每一位的钱数是直接付还是付大的然后找零钱。
dp保留最优即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
*/
char s[M];
ll dp[M][2];//从前往后,第i位,正/倒 给钱 硬币最少是多少
int main()
{
scanf("%s",s+1);
int n=strlen(s+1),f;
memset(dp,0x3f,sizeof(dp));
dp[1][0]=s[1]-'0',dp[1][1]=10-(s[1]-'0')+1;
for(int i=2;i<=n;i++)
{
int tp=s[i]-'0';
int pr=s[i-1]-'0';
// if(pr==0)f=-1;else f=1;
dp[i][0]=min(dp[i-1][0],dp[i-1][1])+tp;
dp[i][1]=min(dp[i-1][0]+1+(10-tp),dp[i-1][1]-1+(10-tp));
// cout<<i<<" "<<dp[i][0]<<" "<<dp[i][1]<<endl;
}
cout<<min(dp[n][0],dp[n][1])<<endl;
return 0;
}
A. Appeal to the Audience
长链剖分,每条链对应一个叶子节点,对应一个参赛者,排序求和即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 3e5+7;
int head[M],cnt;
void init(){cnt=0,memset(head,-1,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
int sz=0;
int n,m,x;
ll a[M],dep[M],du[M],son[M],b[M],nw,siz[M];
void dfs(int u,int fa)
{
dep[u]=dep[fa]+1;
int mx=-1;
for(int i=head[u];i!=-1;i=ee[i].nxt)
{
int v=ee[i].to;
if(v==fa)continue;
dfs(v,u);
siz[u]=max(siz[u],siz[v]+1);
if(siz[v]>mx)mx=siz[v],son[u]=v;
}
}
vector<ll>p;
void dfs2(int u,int fa)
{
if(son[fa]!=u)
{
ll tp=u,z=0;
while(tp!=-1)
{
tp=son[tp];
z++;
}
if(u==0)z--;
p.pb(z);
}
for(int i=head[u];~i;i=ee[i].nxt)
{
int v=ee[i].to;
if(v==fa)continue;
dfs2(v,u);
}
}
int main()
{
cin>>n>>m;
init();memset(son,-1,sizeof(son));
for(int i=1;i<=m;i++)scanf("%lld",&a[i]);
for(int i=1;i<n;i++)scanf("%d",&x),add(x,i),add(i,x),du[i]++,du[x]++;
dfs(0,0);
sort(a+1,a+1+m);
nw=m+1;
ll ans=0;
dfs2(0,0);
// for(int i=0;i<n;i++)cout<<i<<" "<<son[i]<<endl;
sort(p.begin(),p.end());
// for(int i=0;i<p.size();i++)cout<<i<<" "<<p[i]<<endl;
for(int i=0;i<m;i++)ans+=a[i+1]*p[i];
printf("%lld\n",ans);
return 0;
}