前言
根据难度系数补题,大概会补 ACDEFHIJL (因为我的学长也做了这么多题)
L.牛牛学走路
题意 :
模拟上下左右,问什么时候的距离最大
思路 :
对于样例
t
t
t和
n
n
n,范围乘起来不超过
1
e
5
1e5
1e5,所以想了想我们可以使用栈模拟
我们将 L R LR LR和 U D UD UD分为这两组,如果当前栈顶元素不同于当前的 S [ i ] S[i] S[i]那么我们
就开始计算,并且更新答案
但是其实不用栈来模拟,因为使用栈来模拟,对于计算答案的时候,我们总是需要想
一下,虽然思路清晰但是码量较大,所以我们不妨看一下别人的代码,显然他们也是
分了两组,但是使用的是两个变量进行计算,这样子就可以更好的Ac
MyCode
double cal(int x,int y){
return x*x + y*y;
}
void solve()
{
int n;cin>>n;
string s;cin>>s;
ans = 0 ;
while(!xlen.empty()) xlen.pop();
while(!ylen.empty()) ylen.pop();
for(int i = 0 ; i< n;i ++ ){
if(s[i] == 'L' || s[i] == 'R'){
if(xlen.empty()){
xlen.push(s[i]);
ans = max(sqrt(cal(xlen.size(),ylen.size())),ans);
continue;
}
if(xlen.top() == s[i]){
xlen.push(s[i]);
ans = max(sqrt(cal(xlen.size(),ylen.size())),ans);
continue;
}else{
ans = max(sqrt(cal(xlen.size(),ylen.size())),ans);
xlen.pop();
ans = max(sqrt(cal(xlen.size(),ylen.size())),ans);
}
}
if(s[i] == 'U' || s[i] == 'D'){
if(ylen.empty()){
ylen.push(s[i]);
ans = max(sqrt(cal(xlen.size(),ylen.size())),ans);
continue;
}
if(ylen.top() == s[i]){
ylen.push(s[i]);
ans = max(sqrt(cal(xlen.size(),ylen.size())),ans);
continue;
}else{
ans = max(sqrt(cal(xlen.size(),ylen.size())),ans);
ylen.pop();
ans = max(sqrt(cal(xlen.size(),ylen.size())),ans);
}
}
}
printf("%.12lf\n",ans);
}
OtherCode
double get_dist(int x, int y){
return sqrt(x * x + y * y);
}
void solve() {
int n;
cin >> n;
int x = 0, y = 0;
double res = 0;
for(int i = 0 ; i < n ; i ++) {
char c;
cin >> c;
if(c == 'L') x --;
else if(c == 'R') x ++;
else if(c == 'U') y ++;
else y --;
res = max(res, get_dist(x, y));
}
cout << fixed << setprecision(10) << res << "\n";
}
J.小朋友做游戏
题意 :
给你 A 和 B 两组小朋友,B的小朋友不能连在一起
我们需要选出 n 个人,使得价值最大
思路 :
显然因为 A 的小朋友不会打架,所以我们可以从 A 的小朋友这里入手 , 对于当前的状
态,如果确定A的数量为 ia 那么B的数量一定是 n-ia
当且仅当 : ( n − i a < m i n ( n / 2 , b ) ) & & ( n − i a ) > 0 (n-ia < min(n/2,b)) \&\&(n-ia) >0 (n−ia<min(n/2,b))&&(n−ia)>0
这个条件保证了,在 B B B数量够的情况下,确保一定不会出现相连的情况
但是这种情况下还需要考虑价值最大 :
所以我们需要对两个价值数组排序+前缀和处理一下
这样子在每次拿的情况下,我们 就是尽可能多的拿
我的思路太混乱了,不够简洁。所以在做的时候,一开始歪成了 d p [ N ] [ 2 ] dp[N][2] dp[N][2],利用
状态机进行逐个 d p dp dp,但是因为没有审题的原因,没发现是环状,所以总会贪心的多
拿一个 b b b,所以就歪了好久
MyCode
bool cmp(int a,int b){
return a>b;
}
void solve()
{
cin>>a>>b>>n;
for(int i=1;i<=a;i++) cin>>va[i];
for(int i=1;i<=b;i++) cin>>vb[i];
sort(va+1,va+1+a,cmp);sort(vb+1,vb+1+b,cmp);
/**
判断不能的情况
**/
int ans = -1 ;
if(a < (n+1)/2){cout<<-1<<endl;return;}
for(int i=1;i<=a;i++) suma[i] = suma[i-1]+ va[i];
for(int i=1;i<=b;i++) sumb[i] = sumb[i-1]+ vb[i];
for(ia = 0 ;ia<=a;ia++){
ib = n-ia;
if(ib>min(n/2,b)) continue;
if(ib<0)continue;
ans = max(ans,suma[ia]+sumb[ib]);
}
if(ans==-1)
cout<<-1<<endl;
else
cout<<ans<<endl;
}
A.九小时九个人九扇门
思路 :
背包问题求方案数,首先多弄几组你就会发现 数字根 = X%9
所以我们可以使用老方法 :
状态表示 : f [ i ] [ j ] f[i][j] f[i][j] 前 i i i个物品里面选价值是 j j j的方案数
初始化 f [ 0 ] [ 0 ] = 1 f[0][0]=1 f[0][0]=1,然后通过枚举 j j j来进行状态计算即可
MyCode
typedef priority_queue<int,vector<int>,greater<int>> Pri_m;
typedef pair<int,int> pii;
typedef vector<int> VI;
map<int,int> mp;
const int N = 1e5+10,MOD = 998244353;
int f[N][10],a[N];
int n;
inline void cal(int i,int x){
if(x<10) {
a[i] = x;
return;
}
a[i] = x%9;
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++){
int x;cin>>x;
cal(i,x);
}
f[0][0] = 1;
for(int i=1;i<=n;i++){
for(int j=0;j<=8;j++ ){
f[i][(a[i]+j)%9] = (f[i][(a[i]+j)%9] + f[i-1][j])%MOD;
f[i][j] = (f[i-1][j] + f[i][j])%MOD;
}
}
for(int i=1;i<=8;i++)
cout<<f[n][i]<<' ';
cout<<f[n][0]-1<<endl;
}
/**mYHeart is my algorithm**/
int main()
{
//int t;cin>>t;while(t -- )
solve();
return 0;
}
F. 中位数切分
思路 :
贪心的去想,两两分成一组,如果大于
m
m
m贡献加一否则减一
MyCode
void solve()
{
int n,m;cin>>n>>m;
int ans = 0 ;
for(int i=1;i<=n;i++){
int x;cin>>x;
if(x >= m) ++ans;
else --ans;
}
if(ans > 0 )cout<<ans<<endl;
else cout<<-1<<endl;
}