Ball
稍微推一下就知道要么选择左端点要么选择右端点
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const double eps = 1e-8, pi = acos(-1.0);
#define pb push_back
int t;
double dist(int x1, int y1, int x2, int y2)
{
return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2));
}
ll dist2(int x1, int y1, int x2, int y2)
{
return pow(x1 - x2, 2) + pow(y1 - y2, 2);
}
void solve()
{
int l, x, y;
cin >> l >> x >> y;
if (dist2(x, y, 0, 0) <= pow(l, 2))
{
cout << "Yes" << endl;
cout << 0 << endl;
return;
}
if (dist2(x, y, l, 0) <= pow(l, 2))
{
cout << "Yes" << endl;
cout << l << endl;
return;
}
cout << "No" << endl;
return;
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("D:/in.txt", "r", stdin);
freopen("D:/out.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin >> t;
while (t--)
solve();
return 0;
}
Fight Against the Monster
二分答案
如果用一次创造,一次会少(m-k)个
但是要注意最后如果所剩的小于m个了,就不能再继续创造
所以总共的创造次数就是
n
u
m
=
(
x
−
m
)
/
(
m
−
k
)
+
1
num=(x-m)/(m-k)+1
num=(x−m)/(m−k)+1次
所以多创造出的就是
n
u
m
∗
k
num*k
num∗k个
判断
x
+
n
u
m
∗
k
x+num*k
x+num∗k与h的关系即可
#include<bits/stdc++.h>
#define int long long
using namespace std;
int T,m,k,h,l,r,mid;
inline int read(){
char g=getchar();
int s=0;
while (g<'0'||g>'9')g=getchar();
while (g>='0'&&g<='9'){
s=(s<<3)+(s<<1)+g-'0';
g=getchar();
}
return s;
}
bool check(int x){
int maxn=x;
int now=x;
int u;
maxn=x+((x-m)/(m-k)+1)*k;
if (maxn>=h)return true;
return false;
}
signed main(){
T=read();
while (T--){
m=read();
k=read();
h=read();
// scanf("%d%d%d",&m,&k,&h);
if (h<=m){
printf("%lld\n",h);
continue;
}
if (k>=m){
printf("%lld\n",m);
continue;
}
l=m;r=h;
while (l<=r){
mid=(l+r)>>1;
if (check(mid))r=mid-1;
else l=mid+1;
}
printf("%lld\n",l);
}
return 0;
}
树上 MEX 问题
对于这道题而言
一个数MEX=x的贡献就是x*NUM(x)
同时发现MEX是有一种包含关系的
因为你如果想要令
M
E
X
=
x
MEX=x
MEX=x,就必须同时包含0,1……x-1那么多个元素
所以利用这些包含性质,这个问题的答案就可以变成
∑
i
=
1
n
−
1
M
E
X
(
x
>
=
i
)
\sum_{i=1}^{n-1} MEX(x>=i)
∑i=1n−1MEX(x>=i)
想要求解这个问题,我们首先以0号点对应节点为0做一个树形dp求出每个子树内的联通快的数量
d
p
u
=
π
(
d
p
v
+
1
)
dp_u=\pi (dp_v+1)
dpu=π(dpv+1)
然后我们令
c
n
t
i
cnt_i
cnti表示mex值>=i时的联通快个数
同时维护一个集合
S
i
S_i
Si表示MEX=i时包含哪几个点
初始时
C
n
t
1
=
d
p
[
0
]
,
S
1
=
0
Cnt1=dp[0],S_1={0}
Cnt1=dp[0],S1=0
枚举下一个对应的点
x
x
x
如果这个点在集合内,
C
n
t
x
=
C
n
t
x
−
1
.
S
i
=
S
i
−
1
Cnt_x=Cnt_{x-1}.S_i=S_{i-1}
Cntx=Cntx−1.Si=Si−1
不然的话,这个点一定要被选中
所以我们就找一条路径,使得这个路径包含这个点
如何寻找这个路径?
让这个点一直跳父亲,知道这个父亲在集合内,这就是刚好包含这个点的一条路径,同时将路径上的点放入集合内
那么如何更新
C
n
t
呢?
Cnt呢?
Cnt呢?
对于之前的答案,我们对于路径上的点,都是乘以
(
d
p
x
+
1
)
(dp_x+1)
(dpx+1)
表示我们可以选择这个子树,也可以不选
但是这个时候,我们想要选取这些点,是不是就意味着,我们就必须选择这些点?
也就是原来的乘以
d
p
x
+
1
dp_x+1
dpx+1改为乘以
d
p
x
dp_x
dpx
重复以上过程即可
对于复杂度,每一个点最多被加入一次删除一次
因此总体复杂度为
O
(
n
l
o
g
P
)
O(nlogP)
O(nlogP)
其中
l
o
g
P
logP
logP的复杂度是求逆元带来的
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5+100;
const int P = 998244353;
int n;
int f[N],num[N],v[N];
bool vi[N];
int rt;
int cnt[N];
int fa[N];
struct Node{
int y,Next;
}e[2*N];
int len,Linkk[N];
void Dfs(int x,int faa){
int s = 1;
fa[x] = faa;
for (int i = Linkk[x]; i; i = e[i].Next){
int y = e[i].y; if (y == faa) continue;
Dfs(y,x);
s = s*(f[y]+1)%P;
}
f[x] = s;
}
int Power(int x,int y){
int s = 1;
while (y){
if (y&1) s = s*x%P;
x = x*x%P;
y>>=1;
}
return s;
}
void Calc(int x){
if (vi[num[x]]){
cnt[x] = cnt[x-1];
return;
}
int now = x,la;
stack < int > st;
int s = cnt[x-1];
now = num[x];
while (vi[now] == 0) vi[now] = 1 , st.push(now) , now = fa[now];
while (st.size()){
int xx = st.top(); st.pop();
s = s*Power((f[xx]+1)%P,P-2)%P;
s = s*f[xx]%P;
}
cnt[x] = s;
return ;
}
void Insert(int x,int y){
e[++len] = (Node){y,Linkk[x]};
Linkk[x] = len;
}
void Work(){
cin>>n;
for (int i = 1; i <= n; i++) vi[i] = 0,Linkk[i] = 0,cnt[i] = 0;
len = 0;
for (int i = 1; i <= n; i++)
cin>>v[i],num[v[i]] = i;
for (int i = 1,x,y; i < n; i++) cin>>x>>y,Insert(x,y),Insert(y,x);
rt = num[0];
Dfs(rt,0);
cnt[0] = f[rt]; vi[rt] = 1;
for (int i = 1; i < n; i++)
Calc(i);
int s = 0;
for (int i = 0; i < n; i++) s = (s+cnt[i])%P;
cout<<s<<endl;
return;
}
signed main(){
cin.tie(0);
ios::sync_with_stdio(false);
int t; cin>>t; while(t--) Work();
return 0;
}
/*
cnt = 15
cnt = 15
cnt = 12
cnt = 12
cnt = 6
cnt = 6
*/