CF训练1

1985E

看完题目之后 , 第一想法是最暴力的On3 , 对于每个i ,j ,k , 如果它们符合k的体积的话,我们就可以把这个长方体一格一格的移动 , 对于x方向 , 我们一共能移动a - i次 , 那么也就有a -i+1种方法放置 , y轴和z轴也是同理。

当我们信心满满的交上去之后, 就会发现TLE了 , 那么我们可以优化一下On3的算法 , 优化成On2 ,枚举i j , 如果满足 k %(i *j) == 0的话 , 就可以得到k。

void solve(){
    //在n里面选择 x种连续的方式
    //n - x  + 1
    int ans = 0;
    
    cin>>a>>b>>c>>k;
    
    
    int r =0;
   for(int i =1;i<=a;++i){
    for(int j =1;j<=b;++j){
        if(k % (i *j) == 0){
            r = k /(i*j);
        
        int xx = a - i+1;
        int yy  = b - j+1;
        int zz = c - r +1;
        ans = max(ans , xx*yy*zz);
        }
    }
   }
    cout<<ans<<endl;


}

1984C1

这题可以用dp 或者贪心的思路来解
当c+ai是正数时 , 方案1 和 2是没有区别的 , 但是当c+ai是负数的时候 , 就不一样了,当它是负数时,此时小于0,讲道理我们应该启动2了 , 但是我们不知道后面的数会不会也是负数 , 这样它加完后面的数字就会更小了 , 但是绝对值也会对应的更大了。

所以我们可以记录一下它在遍历时的最小值 ,如果最小值小于0 , 我们就把答案 加上它的两倍

void solve(){
    cin>>n;
    for(int i =1;i<=n;++i)cin>>a[i];
    int ans = 0 , mi = INF;
    for(int i =1;i<=n;++i){
        ans +=a[i];
        mi = min(mi , ans);
    }
    if(mi >=0){
        cout<<ans<<endl;
        return;
    }
    else {
        cout<<ans - 2*mi<<endl;
    }


}

 1981B

这是某场div2的B题 , 难度大概在1400

首先 , 我们的所有元素每秒都会跟相邻的元素按位或

对于第i个元素来说

第一秒 : ai-1 | ai | ai+1

由于ai-1 和 ai+1 也在变化  第二秒 :  ai-2 | ai-1 | ai | ai | ai | ai+1 | ai+2 = ai-2 | ai-1 | ai | ai+1 | ai+2

那么我们可以找到规律 ,在第x秒 , ai的变化为 : ai-x | ..... | ai | ... | ai+x

考虑到边界情况有0的存在 最左边的数为 max(0 , ai-x)

我们就有如下代码

void solve(){
	cin>>n>>m;
	l = max(0ll ,n-m);
	r = n+m;
	int ans = 0;
	//从n-m 到n+m 遍历到答案
	for(int i =l;i<=r;++i){
		ans =ans | i;
	}
	cout<<ans;
}

但是这个交上去会发现超时了。那么就引入接下来的一个技巧, 叫快速或和

int ksh(int l ,int r){
    while(l <r){
        l |= (l+1);
    }
    return l;
}

完整代码

int hsum(int l ,int r){
    while(r > l){
        l |=(l+1);
    }
    return l;
}

void solve(){
    cin>>n>>m;
    l = max(0ll , n-m); 
    r = n+m;
    //从 n-m 或到n+m
    cout<<hsum(l , r)<<endl;
}

1980D

我们可以用b数组把gcd的这个先给表示出来 ,遍历b数组 , 如果遇到bi > bi+1的这种情况 ,我们可以考虑删掉第bi个点 , bi-1个点 ,bi+1个点

首先在i之前的所有数字肯定是没有问题的 , 主要就是bi-1  bi 和bi+1 这三个数字 , 首先bi-1由a-1 . ai组成  bi 由ai和ai+1组成 , bi+1由 ai+1和ai+2组成 , 也就是对于ai-1 ai  ai+1 ai+2我们依次考虑删除其中一个后, 看看是否能满足题意, 若不能则输出NO , 若能 ,则判断下一个不符合情况的点

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
const int N =2e5+9;
#define INF 0x3f3f3f3f
int gcd(int x , int y){
  return y ==0?x : gcd(y , x%y);
}
int lcm(int x , int y){
  return x*y/gcd(x,y);
}
int n;
void solve(){
    cin>>n;
    vector<int>a(n+1);
    for(int i =1;i<=n;++i)cin>>a[i];
    vector<int>b(n+1);
    for(int i =1;i<n;++i)b[i] = gcd(a[i] , a[i+1]);

    auto check = [&](int p){
        auto c = a;
        c.erase(c.begin()+1+p);//删除第p个元素
        vector<int>d(n+1);
        for(int i =1;i<=n-2;++i){
            d[i] = gcd(c[i] , c[i+1]);
            if(d[i] < d[i-1])return false;
        }
        return true;
    };

    for(int i =1;i<n-1;++i){
        if(b[i] > b[i+1]){
            if(!check(i-1) && !check(i) && !check(i+1) && !check(i+2)){
                cout<<"NO"<<endl;
                return;
            }
        }
    }
    cout<<"YES"<<endl;

}

signed main(){
    ios::sync_with_stdio(false);
    cout.tie(0);
    cin.tie(0);
    int _;cin>>_;
    while(_--)solve();
    return 0;
}



	   

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值