A.打怪
题意:
你
有
h
的
血
量
,
a
的
攻
击
你有h的血量,a的攻击
你有h的血量,a的攻击
怪
兽
有
H
的
血
量
,
A
的
攻
击
怪兽有H的血量,A的攻击
怪兽有H的血量,A的攻击
每
次
你
先
出
手
,
轮
流
攻
击
,
血
量
小
于
等
于
0
就
死
每次你先出手,轮流攻击,血量小于等于0就死
每次你先出手,轮流攻击,血量小于等于0就死
问
不
死
的
前
提
最
多
能
打
多
少
怪
问不死的前提最多能打多少怪
问不死的前提最多能打多少怪
不
会
死
输
出
−
1
不会死输出-1
不会死输出−1
题解:
首
先
不
会
死
就
说
明
,
每
次
都
能
一
次
解
决
怪
兽
即
a
>
=
H
首先不会死就说明,每次都能一次解决怪兽即a>=H
首先不会死就说明,每次都能一次解决怪兽即a>=H
然
后
算
怪
兽
每
次
的
攻
击
次
数
,
由
于
你
是
先
手
,
所
以
最
后
一
击
怪
兽
不
会
还
手
然后算怪兽每次的攻击次数,由于你是先手,所以最后一击怪兽不会还手
然后算怪兽每次的攻击次数,由于你是先手,所以最后一击怪兽不会还手
就
算
还
差
一
次
杀
死
怪
兽
的
次
数
,
乘
上
怪
兽
的
攻
击
就算还差一次杀死怪兽的次数,乘上怪兽的攻击
就算还差一次杀死怪兽的次数,乘上怪兽的攻击
在
自
己
不
死
的
前
提
看
自
己
能
承
受
多
少
次
,
就
是
杀
死
多
少
只
怪
兽
在自己不死的前提看自己能承受多少次,就是杀死多少只怪兽
在自己不死的前提看自己能承受多少次,就是杀死多少只怪兽
AC代码
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=3e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int t;
cin>>t;
while(t--){
int h,a,H,A;
cin>>h>>a>>H>>A;
if(a>=H)cout<<-1;
else {
int k=(H-1)/a;
int p=A*k;
cout<<(h-1)/p;
}
cout<<endl;
}
return 0;
}
B.吃水果
题意:
有
a
个
苹
果
和
b
个
香
蕉
有a个苹果和b个香蕉
有a个苹果和b个香蕉
每
天
必
须
同
时
吃
掉
1
个
苹
果
和
1
个
香
蕉
每天必须同时吃掉1个苹果和1个香蕉
每天必须同时吃掉1个苹果和1个香蕉
或
者
你
可
以
使
某
个
水
果
数
量
翻
倍
或者你可以使某个水果数量翻倍
或者你可以使某个水果数量翻倍
问
最
少
多
天
能
让
两
个
水
果
都
没
有
问最少多天能让两个水果都没有
问最少多天能让两个水果都没有
题解:
贪
心
+
模
拟
贪心+模拟
贪心+模拟
先
让
数
量
小
的
每
次
翻
倍
,
直
到
翻
倍
后
比
另
一
个
大
先让数量小的每次翻倍,直到翻倍后比另一个大
先让数量小的每次翻倍,直到翻倍后比另一个大
然
后
开
始
吃
,
吃
到
又
可
以
翻
倍
的
时
候
继
续
翻
倍
然后开始吃,吃到又可以翻倍的时候继续翻倍
然后开始吃,吃到又可以翻倍的时候继续翻倍
直
到
a
=
=
b
结
束
直到a==b结束
直到a==b结束
AC代码
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=3e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int t;
cin>>t;
while(t--){
int a,b;
cin>>a>>b;
int ans=0;
if(a>b)swap(a,b);
while(1){
if(a==b){cout<<ans+a<<endl;break;}
if(a*2<=b)a*=2,ans++;
if(a*2>b)a--,b--,ans++;
}
}
return 0;
}
C.四个选项
题意:
12
道
选
择
题
,
每
道
答
案
可
能
是
A
,
B
,
C
,
D
12道选择题,每道答案可能是A,B,C,D
12道选择题,每道答案可能是A,B,C,D
要
求
12
道
中
有
a
道
A
,
b
道
B
,
c
道
C
,
d
道
D
要求12道中有a道A,b道B,c道C,d道D
要求12道中有a道A,b道B,c道C,d道D
并
且
给
出
m
个
约
束
条
件
,
每
次
保
证
给
出
的
x
和
y
具
有
相
同
答
案
并且给出m个约束条件,每次保证给出的x和y具有相同答案
并且给出m个约束条件,每次保证给出的x和y具有相同答案
题解:
D
F
S
+
并
查
集
DFS+并查集
DFS+并查集
首
先
用
并
查
集
求
出
有
多
少
个
相
同
答
案
的
集
合
首先用并查集求出有多少个相同答案的集合
首先用并查集求出有多少个相同答案的集合
然
后
进
行
D
F
S
,
对
每
个
集
合
进
行
赋
予
答
案
,
并
维
护
每
个
答
案
的
状
态
然后进行DFS,对每个集合进行赋予答案,并维护每个答案的状态
然后进行DFS,对每个集合进行赋予答案,并维护每个答案的状态
直
到
和
题
目
要
求
相
等
a
n
s
+
+
直到和题目要求相等ans++
直到和题目要求相等ans++
剪
枝
:
每
次
每
个
答
案
加
的
集
合
元
素
数
量
不
能
超
过
这
道
题
的
答
案
剪枝:每次每个答案加的集合元素数量不能超过这道题的答案
剪枝:每次每个答案加的集合元素数量不能超过这道题的答案
AC代码
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=3e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
vector<int> v;
int a,b,c,d,m,n;
int fa[20],cnt[20],ans;
int find(int x){
if(fa[x]==x)return x;
return fa[x]=find(fa[x]);
}
void dfs(int i,int xa,int xb,int xc,int xd){
if(xa==a&&xb==b&&xc==c&&xd==d)ans++;
if(i==n)return;
if(xa+v[i]<=a)dfs(i+1,xa+v[i],xb,xc,xd);
if(xb+v[i]<=b)dfs(i+1,xa,xb+v[i],xc,xd);
if(xc+v[i]<=c)dfs(i+1,xa,xb,xc+v[i],xd);
if(xd+v[i]<=d)dfs(i+1,xa,xb,xc,xd+v[i]);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
cin>>a>>b>>c>>d>>m;
for(int i=1;i<=12;i++)fa[i]=i;
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
int p=find(x),q=find(y);
fa[p]=q;
}
for(int i=1;i<=12;i++)cnt[find(i)]++;
for(int i=1;i<=12;i++)
if(cnt[i])v.pb(cnt[i]);
n=v.size();
dfs(0,0,0,0,0);
cout<<ans;
return 0;
}
D.最短路变短了
题意:
有
n
个
点
,
m
条
有
向
边
,
每
条
边
带
权
有n个点,m条有向边,每条边带权
有n个点,m条有向边,每条边带权
问
如
果
翻
转
某
一
条
边
,
权
值
不
变
,
起
点
终
点
互
换
,
是
否
会
让
最
短
路
变
短
问如果翻转某一条边,权值不变,起点终点互换,是否会让最短路变短
问如果翻转某一条边,权值不变,起点终点互换,是否会让最短路变短
询
问
q
次
询问q次
询问q次
题解:
先
用
d
i
j
算
源
点
为
1
和
源
点
为
n
开
始
的
到
每
个
点
的
最
短
路
径
先用dij算源点为1和源点为n开始的到每个点的最短路径
先用dij算源点为1和源点为n开始的到每个点的最短路径
最
初
的
最
短
路
径
也
可
以
算
出
假
设
为
d
n
最初的最短路径也可以算出假设为d_n
最初的最短路径也可以算出假设为dn
如
果
想
要
某
条
路
翻
转
会
使
得
最
短
路
变
小
如果想要某条路翻转会使得最短路变小
如果想要某条路翻转会使得最短路变小
说
明
新
的
最
短
路
一
定
会
经
过
这
条
路
说明新的最短路一定会经过这条路
说明新的最短路一定会经过这条路
所
以
只
需
要
用
1
到
这
条
边
新
的
起
点
的
距
离
加
上
n
到
这
条
边
新
的
终
点
的
距
离
加
上
这
条
边
的
权
值
所以只需要用1到这条边新的起点的距离~~加上 n到这条边新的终点的距离~~加上这条边的权值
所以只需要用1到这条边新的起点的距离 加上n到这条边新的终点的距离 加上这条边的权值
看
这
个
值
是
否
小
于
d
n
,
即
可
判
断
看这个值是否小于d_n,即可判断
看这个值是否小于dn,即可判断
AC代码
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e5+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
struct edge{
ll u,v,w;
}e[200010];
int n,m;
vector<pll> g1[maxn],g2[maxn];
ll d1[maxn],d2[maxn];
void dij(ll dis[],vector<pll> g[],int s){
for(int i=1;i<=n;i++)dis[i]=inf*inf;
dis[s]=0;
priority_queue<pll,vector<pll>,greater<pll> > q;
q.push(mp(0,s));
while(!q.empty()){
pll p=q.top();
q.pop();
int u=p.se;
if(dis[u]<p.fi)continue;
for(auto i:g[u]){
int v=i.fi;
ll w=i.se;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
q.push(mp(dis[v],v));
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
cin>>n>>m;
for(int i=1;i<=m;i++){
ll u,v,w;
cin>>u>>v>>w;
g1[u].pb(mp(v,w));
g2[v].pb(mp(u,w));
e[i]={u,v,w};
}
dij(d1,g1,1);dij(d2,g2,n);
int q;cin>>q;
while(q--){
ll x;
cin>>x;
if(d1[e[x].v]+d2[e[x].u]+e[x].w<d1[n])cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}