Codeforces Round #748 (Div. 3)
A.Elections
题意:
给出三个人的票数,一个人票数要严格高于其余两人才能当选,问每个人当选需要在得到多少票。
思路:
枚举这个人要再得到多少票能超过另一个人,取最大值。
代码:
#include<bits/stdc++.h>
#define fi first
#define se second
#define ll long long
#define mp make_pair
#define pb push_back
#define ls x<<1
#define rs x<<1|1
#define lson x<<1,l,mid
#define rson x<<1|1,mid+1,r
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define cl(x,y) memset(x,y,sizeof(x))
#define nxtp(a,n) next_permutation(a+1,a+n+1)
#define mem(x,y,n) memset(x,y,sizeof(int)*(n+5))
const int N=1e6+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
const double pi=acos(-1);
const double INF=1e18;
using namespace std;
int a[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--)
{
int i,j;
for(i=1;i<=3;i++)
cin>>a[i];
for(i=1;i<=3;i++)
{
int ans=0;
for(j=1;j<=3;j++)
if(i!=j)
ans=max(ans,max(a[j]-a[i]+1,0));
cout<<ans<<" ";
}
cout<<endl;
}
return 0;
}
B. Make it Divisible by 25
题意:
给一个含前导 0 0 0的数,问至少删掉几个数字使这个它能被 25 25 25整除。
思路:
能被 25 25 25整除的数的后两位只有 4 4 4种可能: 00 , 25 , 50 , 75 00,25,50,75 00,25,50,75。枚举找到公共后缀中最近的一个。
代码:
#include<bits/stdc++.h>
#define fi first
#define se second
#define ll long long
#define mp make_pair
#define pb push_back
#define ls x<<1
#define rs x<<1|1
#define lson x<<1,l,mid
#define rson x<<1|1,mid+1,r
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define cl(x,y) memset(x,y,sizeof(x))
#define nxtp(a,n) next_permutation(a+1,a+n+1)
#define mem(x,y,n) memset(x,y,sizeof(int)*(n+5))
const int N=1e6+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
const double pi=acos(-1);
const double INF=1e18;
using namespace std;
string s[5]={"","52","05","57","00"};
string t;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--)
{
cin>>t;
reverse(all(t));
int n=t.length(),i,j;
int ans=inf;
for(i=1;i<=4;i++)
{
int p,v=0;
for(j=0;j<n;j++)
if(s[i][v]==t[j])
{
v++;
if(v==2)
{
p=j;
break;
}
}
ans=min(ans,j-1);
}
cout<<ans<<endl;
}
return 0;
}
C. Save More Mice
题意:
有 k k k只老鼠和 1 1 1只猫。老鼠初始在 a i a_i ai,洞在 n n n,每次你能使一只老鼠向前移动一个位置,如果它到达 n n n就安全了。猫初始在位置 0 0 0,每次向前移动一个位置,在老鼠移动之后,猫会移动,如果这个位置上有老鼠,它们就会被猫吃掉。问最多有多少只老鼠存活。
思路:
发现让一只老鼠活下来的步数为 n − a i n-a_i n−ai,要尽可能多的老鼠活下来,那么步数越少就越先走。猫一共能走 n n n步,如果累计值大于等于这个值就说明老鼠会被猫吃掉。
代码:
#include<bits/stdc++.h>
#define fi first
#define se second
#define ll long long
#define mp make_pair
#define pb push_back
#define ls x<<1
#define rs x<<1|1
#define lson x<<1,l,mid
#define rson x<<1|1,mid+1,r
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define cl(x,y) memset(x,y,sizeof(x))
#define nxtp(a,n) next_permutation(a+1,a+n+1)
#define mem(x,y,n) memset(x,y,sizeof(int)*(n+5))
const int N=1e6+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
const double pi=acos(-1);
const double INF=1e18;
using namespace std;
int a[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--)
{
int n,k,i;
cin>>n>>k;
for(i=1;i<=k;i++)
{
int x;
cin>>x;
a[i]=n-x;
}
sort(a+1,a+k+1,[](int x,int y){
return x<y;
});
int sum=0,tot=0;
for(i=1;i<=k;i++)
{
if(sum+a[i]<n)
{
tot++;
sum+=a[i];
}
else
break;
}
cout<<tot<<endl;
}
return 0;
}
D1. All are Same
题意:
给你 n n n个数,你需要找到最大的一个 k k k,满足你可以使任意数减任意次 k k k后,所有数字相等。如果所有数字都可以是 k k k,输出“-1”。
思路:
假设只有两个数
a
,
b
a,b
a,b,可以发现
k
k
k满足能被
∣
a
−
b
∣
|a-b|
∣a−b∣整除。那么对于
n
n
n个数,如果
k
k
k满足能被任意
∣
a
i
−
a
j
∣
|a_i-a_j|
∣ai−aj∣整除,那么它就是我们要找的
k
k
k。
又假设存在三个数
x
,
y
,
z
x,y,z
x,y,z满足上述条件,那么可以得到
∣
x
−
y
∣
=
a
k
,
∣
y
−
z
∣
=
b
k
,
∣
x
−
z
∣
=
c
k
|x-y|=ak,|y-z|=bk,|x-z|=ck
∣x−y∣=ak,∣y−z∣=bk,∣x−z∣=ck,对于三个表达式正负号讨论一下可以发现
c
k
ck
ck一直可以由
a
k
,
b
k
ak,bk
ak,bk构造到,说明如果
k
k
k能被
∣
x
−
y
∣
,
∣
y
−
z
∣
|x-y|,|y-z|
∣x−y∣,∣y−z∣整除,那么它就能被
∣
x
−
z
∣
|x-z|
∣x−z∣整除。
所以我们只需要计算相邻两项数差的绝对值的最大公约数就行了。-1的情况就是所有数字都相等的情况。
代码:
#include<bits/stdc++.h>
#define fi first
#define se second
#define ll long long
#define mp make_pair
#define pb push_back
#define ls x<<1
#define rs x<<1|1
#define lson x<<1,l,mid
#define rson x<<1|1,mid+1,r
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define cl(x,y) memset(x,y,sizeof(x))
#define nxtp(a,n) next_permutation(a+1,a+n+1)
#define mem(x,y,n) memset(x,y,sizeof(int)*(n+5))
const int N=1e6+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
const double pi=acos(-1);
const double INF=1e18;
using namespace std;
int a[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--)
{
int n,i;
cin>>n;
int g=0;
for(i=1;i<=n;i++)
cin>>a[i];
for(i=1;i<n;i++)
g=__gcd(g,abs(a[i]-a[i+1]));
cout<<(g==0?-1:g)<<endl;
}
return 0;
}
D2. Half of Same
题意:
给你 n n n个数,你需要找到最大的一个 k k k,满足你可以使任意数减任意次 k k k后,至少有一半的数字相等。如果所有数字都可以是 k k k,输出“-1”。
思路:
由上一题的思路出发,我们可以看出答案是相邻两项数差的绝对值的因子。那么我们枚举所有的因子,看看同余的数的个数是否会大于等于 n 2 \cfrac{n}{2} 2n。
代码:
#include<bits/stdc++.h>
#define fi first
#define se second
#define ll long long
#define mp make_pair
#define pb push_back
#define ls x<<1
#define rs x<<1|1
#define lson x<<1,l,mid
#define rson x<<1|1,mid+1,r
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define cl(x,y) memset(x,y,sizeof(x))
#define nxtp(a,n) next_permutation(a+1,a+n+1)
#define mem(x,y,n) memset(x,y,sizeof(int)*(n+5))
const int N=1e6+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
const double pi=acos(-1);
const double INF=1e18;
using namespace std;
int a[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--)
{
int n,i,j,f=0;
cin>>n;
map<int,int> m;
for(i=1;i<=n;i++)
{
cin>>a[i];
m[a[i]]++;
}
for(auto [x,y]:m)
if(y>=n/2)
{
cout<<-1<<endl;
f=1;
}
if(f)
continue;
set<int,greater<int>> s;
for(i=1;i<=n;i++)
for(j=i+1;j<=n;j++)
{
int v=abs(a[i]-a[j]),k;
for(k=1;k*k<=v;k++)
if(v%k==0)
{
s.insert(k);
s.insert(v/k);
}
}
for(auto x:s)
{
f=0;
map<int,int> sum;
for(i=1;i<=n;i++)
{
int v=(a[i]%x+x)%x;
sum[v]++;
if(sum[v]>=n/2)
{
cout<<x<<endl;
f=1;
break;
}
}
if(f)
break;
}
}
return 0;
}
E. Gardener and Tree
题意:
给你一颗 n n n个结点的树,每一轮删掉它的叶子结点,一共删 k k k轮,问最后还剩下多少结点。
思路:
按照题意进行模拟,利用拓扑排序的思路,一轮一轮的删结点,最后统计还剩多少结点就行了。
记得特判
n
=
1
n=1
n=1的情况!
代码:
#include<bits/stdc++.h>
#define fi first
#define se second
#define ll long long
#define mp make_pair
#define pb push_back
#define ls x<<1
#define rs x<<1|1
#define lson x<<1,l,mid
#define rson x<<1|1,mid+1,r
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define cl(x,y) memset(x,y,sizeof(x))
#define nxtp(a,n) next_permutation(a+1,a+n+1)
#define mem(x,y,n) memset(x,y,sizeof(int)*(n+5))
const int N=1e6+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
const double pi=acos(-1);
const double INF=1e18;
using namespace std;
vector<int> e[N];
int d[N],vis[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--)
{
int n,i,k;
cin>>n>>k;
for(i=1;i<=n;i++)
{
e[i].clear();
d[i]=0;
vis[i]=0;
}
for(i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
e[u].pb(v);
e[v].pb(u);
d[u]++;
d[v]++;
}
queue<pii> q;
for(i=1;i<=n;i++)
if(d[i]==1 || d[i]==0)
q.push(mp(i,1));
while(!q.empty())
{
pii pre=q.front();
q.pop();
if(pre.se>k)
break;
int u=pre.fi;
vis[u]=1;
for(auto v:e[u])
{
if(vis[v])
continue;
d[v]--;
if(d[v]==1)
q.push(mp(v,pre.se+1));
}
}
int sum=0;
for(i=1;i<=n;i++)
if(vis[i]==0)
sum++;
cout<<sum<<endl;
}
return 0;
}
G. Changing Brackets
题意:
给你一个括号序列,包含’(’,’)’,’[’,’]’。有两种操作:
- '(‘和’)‘相互转换或者’[‘和’]'相互转换,代价为 0 0 0。
- ‘[‘变成’(‘或者’]‘变成’)’,代价为 1 1 1。
q q q次询问一个区间 [ l , r ] [l,r] [l,r],令 [ l , r ] [l,r] [l,r]区间的括号变成合法序列最少的代价是多少,每次询问不会影响下次询问。
思路:
我们可以发现操作
1
1
1不需要代价,只有操作
2
2
2需要代价。就是说,我们只需要考虑什么时候将方括号变成圆括号。
可以发现,任意奇偶数位置上相同类型的括号都可以通过操作
1
1
1变成合法的。也就是说,如果一个奇数位上方括号找不到任意一个偶数位上的方括号进行配对,那么它就需要变成圆括号。
那么我们可以发现,如果奇数位上方括号的个数为
x
x
x,偶数为上的方括号为
y
y
y,那么就至少需要改变
∣
x
−
y
∣
|x-y|
∣x−y∣个括号。
对于
q
q
q次询问,利用前缀和统计一下即可。
代码:
#include<bits/stdc++.h>
#define fi first
#define se second
#define ll long long
#define mp make_pair
#define pb push_back
#define ls x<<1
#define rs x<<1|1
#define lson x<<1,l,mid
#define rson x<<1|1,mid+1,r
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define cl(x,y) memset(x,y,sizeof(x))
#define nxtp(a,n) next_permutation(a+1,a+n+1)
#define mem(x,y,n) memset(x,y,sizeof(int)*(n+5))
const int N=1e6+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
const double pi=acos(-1);
const double INF=1e18;
using namespace std;
char a[N];
int x[N],y[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--)
{
cin>>a+1;
int i;
int n=strlen(a+1);
for(i=1;i<=n;i++)
{
if(i&1)
{
x[i]=x[i-1]+(a[i]=='[' || a[i]==']');
y[i]=y[i-1];
}
else
{
x[i]=x[i-1];
y[i]=y[i-1]+(a[i]=='[' || a[i]==']');
}
}
int q;
cin>>q;
while(q--)
{
int l,r;
cin>>l>>r;
int xx=x[r]-x[l-1],yy=y[r]-y[l-1];
int ans=abs(xx-yy);
cout<<ans<<endl;
}
}
return 0;
}