前言:
今天同时做两个比赛(B组不一定今天能改完),但是C组做完了,最后一题单独放(太难了)
题目
JZOJ 3792 分队问题
题目:
n个选手分成若干只队伍。第i个选手要求所属队伍 ≥ a [ i ] \geq a[i] ≥a[i]人,满足所有要求时最多有多少只队伍。
分析
贪心,用now表示当前队伍的要求,先降序排列,每完成一个选手的要求,使now减1,当now为0时组建新的队伍,特别地,当存在队伍并在新的队伍,找到更小的要求 a i a_i ai, n o w = a i now=a_i now=ai,因为选手的要求越低,队伍数越多,当然在新队伍并且要求更高的可以放在前一个队伍,因为一旦有新的队伍,之前的队伍可以无限制加入选手。时间复杂度:O(n)
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
int n,a[1000001],ans,now;
int in(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
int main(){
n=in(); bool flag=1;
for (int i=1;i<=n;i++) a[i]=in();
stable_sort(a+1,a+1+n); now=a[n];
for (int i=n;i>=1;i--){
if (a[i]<now&&!flag) now=a[i]; now--;
if (!now) now=a[i],ans++,flag=0;
}
return !printf("%d",ans);
}
JZOJ 3793 数字对
题目
数字对(a, b)可以变为(a+b, b)或(a, a+b)。最少多少次可将(1, 1)变为至少有一个数字为n的数字对。
分析
它使我想到了更相减损法,
g
c
d
(
a
,
b
)
=
g
c
d
(
a
,
b
−
a
)
或
g
c
d
(
a
−
b
,
b
)
(
a
≤
b
或
b
≤
a
)
gcd(a,b)=gcd(a,b-a)或gcd(a-b,b)(a\leq b或b\leq a)
gcd(a,b)=gcd(a,b−a)或gcd(a−b,b)(a≤b或b≤a)
只要计算更相减损的次数即可,但是容易超时,所以可以想到
g
c
d
(
a
,
b
)
=
g
c
d
(
b
,
a
m
o
d
  
b
)
gcd(a,b)=gcd(b,a\mod b)
gcd(a,b)=gcd(b,amodb)
然而,
a
m
o
d
  
b
a\mod b
amodb可以表示为
a
−
⌊
a
/
b
⌋
∗
b
a-\lfloor a/b \rfloor*b
a−⌊a/b⌋∗b,所以次数就是
⌊
a
/
b
⌋
\lfloor a/b \rfloor
⌊a/b⌋,对于特判情况,b=0时无解,b=1时是a-1。
代码
#include <cstdio>
using namespace std;
int n,ans=233333332;
int answer(int a,int b){
if (b==1) return a-1;
else if (!b) return 233333333;
else return a/b+answer(b,a%b);
}
int min(int a,int b){return (a<b)?a:b;}
int main(){
scanf("%d",&n);
for (int i=1;i<=(n+1)>>1;i++) ans=min(ans,answer(n,i));
return !printf("%d",ans);
}
JZOJ 3794 高级打字机
后续
洛谷 2062 分队问题 2090 数字对 1383 高级打字机