H. 唔...这个我真的能做到吗。

题意:有两种温度的水,一种是热水h度的,一种是c度的冷水,倒水的顺序是这样的,热,冷,热,冷,热,冷,最后的水温是所有杯水加起来的平均值,比如倒了7杯热的,6杯凉的。$t=(7 * h+6 * c)/(6+7)$,问倒水最少多少次,可以让温度最接近H度

思路:如果倒水次数为偶数,那么温度就是(h+c)/2,如果这个温度是大于T的,那么就倒两次即可,因为如果是奇数次倒水,次数越多,温度越高的,就会逐步远离T,反之,我们知道,水温增加到一定程度,我们冷水倒x次时,会比冷水倒x+1次更接近H,那么我们可以二分答案,二分倒冷水的次数即可

代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int,int>
#define double long double
#define  ld long double
int a[105][105];
void solve() {
    int c,h,t;
    cin>>h>>c>>t;
    int ans=0;
//    if(h==t){
//        cout<<"1\n";
//        return;
//    }
    if(c+h>=2*t){
        cout<<2<<endl;
        return;

    }
    auto check=[&](int x){
        double ans=(double)((x+1)*h+x*c)/(double)(2*x+1);
        return fabs(ans-(double)t);
    };
    int x=(t-h)/(h+c-2*t);
    int l=0,r=1e9;
    while(l<=r){
        int mid=l+r>>1;
        if(check(mid)<=check(mid+1)){
            ans=mid;
            r=mid-1;
        }
        else{
            l=mid+1;
        }
    }
    cout<<ans*2+1<<endl;

//
//    ld v=(ld)1e9;
//    for (int i = max((int )0,x-1); i <=x+1 ; ++i) {
//        ld res=abs((ld)((i+1)*h+i*c)/(ld)(2*i+1)-(ld)(t));
////        ld vi = abs( (ld) ((i + 1) * h + i * c) / (ld)(2 * i + 1) - (ld)(T));
//        if(res<v){
//            v=res;
//            ans=2*i+1;
//        }
//    }
//    cout<<ans<<'\n';

}
signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    int t=1;
    cin>>t;
    while (t--){
        solve();
    }
}

K. 让德克萨斯来担任队长!

题意: 给定一个数组,但不是求最大的字串和,而是求去掉某个区间的最大值,能够获得的最大的字串和为多少

思路:最大字串和可以On的求出来,那么去掉最大值其实就是假设当前的最大值是K,那么大于K的都设为区间的断点,然后我们枚举K,求加上断点之后的最大字串和,减去K,即是我们的答案

diamond:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int,int>
int a[105][105];
void solve() {
    int ans=0;
    int n;
    cin>>n;
    vector<int>a(n);
    for (int i = 0; i <n ; ++i) {
        cin>>a[i];
    }
    for (int k = 0; k <=30 ; ++k) {
        auto b=a;
        for (auto &i:b) {
            if(i>k)i=INT_MIN;
        }
        int res=0,cnt=0;
        for (auto i :b) {
            cnt+=i;
            if(cnt<0)cnt=0;
            res=max(res,cnt);
        }
        ans=max(res-k,ans);
    }
    cout<<ans<<'\n';

}
signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    int t=1;
//    cin>>t;
    while (t--){
        solve();
    }
}

F. 我才不会一个人的时候跟仿生海龙聊天!

题意:有四种类型的菜,每种类型的菜有ni道菜可以选择,每道菜的价格是aj,有些菜肴不能搭配,一二种菜有m1对菜不能搭配,索引值为x,y。二三种菜有m2对菜不能搭配,三四种菜有m3种不能搭配,每一种菜都要选择一种,问如何才能最小化花费,如果不能搭配,则输出-1

思路:我们开一个multiset,枚举每一个m,然后枚举每一个右边的值,然后枚举他的边,我们从set里面删除所有的,最后求最大,删完了,说明这个位置就是无穷大

代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define  int long long

const  int mod=998244353;
const int INF=1e15;
const int maxn=150050;

void solve() {
    int n1,n2,n3,n4;
    cin>>n1>>n2>>n3>>n4;
    vector<int>a(n1),b(n2),c(n3),d(n4);
    for (int i = 0; i <n1 ; ++i) {
        cin>>a[i];
    }
    for (int i = 0; i <n2 ; ++i) {
        cin>>b[i];
    }
    for (int i = 0; i <n3 ; ++i) {
        cin>>c[i];
    }
    for (int i = 0; i <n4 ; ++i) {
        cin>>d[i];
    }
    int m1,m2,m3;
    vector<int>g1[n2];
    vector<int >g2[n3];
    vector<int>g3[n4];
    cin>>m1;
    for (int i = 0; i <m1 ; ++i) {
        int x,y;
        cin>>x>>y;
        x--,y--;
        g1[y].push_back(x);
    }
    cin>>m2;
    for (int i = 0; i <m2 ; ++i) {
        int x,y;
        cin>>x>>y;
        x--,y--;
        g2[y].push_back(x);
    }
    cin>>m3;
    for (int i = 0; i <m3 ; ++i) {
        int x,y;
        cin>>x>>y;
        x--,y--;
        g3[y].push_back(x);
    }
    multiset<int>st;
    for (auto i:a) {
        st.insert(i);
    }
    for (int i = 0; i <n2 ; ++i) {
        vector<int>p;
        for (auto k:g1[i]) {
            st.erase(st.lower_bound(a[k]));
            p.push_back(a[k]);
        }
        if(st.empty()){
            b[i]=INF;
        }
        else{
            b[i]+=*st.begin();
        }
        for (auto j:g1[i]) {
            st.insert(a[j]);
        }
    }
    st.clear();
    for (auto i:b) {
        st.insert(i);
    }
    for (int i = 0; i <n3 ; ++i) {
        vector<int>p;
        for (auto k:g2[i]) {
            st.erase(st.lower_bound(b[k]));
            p.push_back(a[k]);
        }
        if(st.empty()){
            c[i]=INF;
        }
        else{
            c[i]+=*st.begin();
        }
        for (auto j:g2[i]) {
            st.insert(b[j]);
        }
    }
    st.clear();
    for (auto i:c) {
        st.insert(i);
    }
    for (int i = 0; i <n4 ; ++i) {
        vector<int>p;
        for (auto k:g3[i]) {
            st.erase(st.lower_bound(c[k]));
            p.push_back(c[k]);
        }
        if(st.empty()){
            d[i]=INF;
        }
        else{
            d[i]+=*st.begin();
        }
        for (auto j:g3[i]) {
            st.insert(c[j]);
        }
    }
    int ans= *min_element(d.begin(),d.end());
    if(ans>=INF)ans=-1;
    cout<<ans<<endl;

}

signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t=1;
    //cin>>t;
    while (t--){
        solve();
    }

}

简洁版大神diamond:

#include <bits/stdc++.h>

using namespace std;

#define int long long
const int inf = 1e18;

int32_t main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    vector<int> n(4);
    for (auto &i: n) cin >> i;
    vector<vector<int>> a(4);
    for (int i = 0; i < 4; i++) {
        a[i] = vector<int>(n[i]);
        for (auto &j: a[i]) cin >> j;
    }
    for (int i = 1, m; i < 4; i++) {
        cin >> m;
        vector<vector<int>> e(n[i] + 1);
        for (int x, y; m; m--)
            cin >> x >> y, x--, y--, e[y].push_back(x);
        multiset<int> cnt;
        for (auto j: a[i - 1])
            cnt.insert(j);
        for (int j = 0; j < n[i]; j++) {
            for (auto k: e[j])
                cnt.erase(cnt.lower_bound(a[i - 1][k]));
            if (cnt.empty()) a[i][j] = inf;
            else a[i][j] += *cnt.begin();
            for (auto k: e[j])
                cnt.insert(a[i - 1][k]);
        }
    }
    int res = *min_element(a[3].begin(), a[3].end());
    if( res >= inf ) res = -1;
    cout << res;
    return 0;
}

A. 把你砍成两半!

题意:求有多少个长度为k的序列a,满足以下条件,对于所有的 $ai$,$ai<ai+1$,$1<=ai<=n$,对于任意值x,对所选序列的全排列任意顺序,取模之后,答案相同

思路:

$x%a%b=x%b%a$,又因为b>a,所以左边=$x%a$,所以$x≡x%b(mod a)$,那么设$x=tb+y$,右边$(tb+y)%b=y$,得到$tb+y≡y(mod a)$,由于t是任意的,那么只有a能够整除b时,等式才能恒成立,那么我们推广到整个数列,得出结论,序列中的每一个数都是最小数的倍数


那么我们就可以枚举第一位数字,然后组合数选出k-1个倍数即可。

diamond:

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>PII;
const int N=1e5+5,M=1e5+5,INF=0x3f3f3f3f,Mod=998244353;
#define  mod Mod
const double eps=1e-8;
typedef long long ll;
#define int long long
//ll a,b;
//int n,p;
int n;
int ksm(int x,int y,int p){
    int res=1;
    while(y){
        if(y&1)res=(ll)res*x%p;
        x=(ll)x*x%p;
        y>>=1;
    }
    return res;
}
int c(int a,int b,int p){
    if(b>a)return 0;
    int res=1;
    for(int i=1,j=a;i<=b;++i,--j){
        res=(ll)res*j%p;
        res=(ll)res*ksm(i,p-2,p)%p;
    }
    return res;
}
int Lucas(ll a,ll b,int p){
    if(a<p&&b<p)return c(a,b,p);
    return (ll)c(a%p,b%p,p)*Lucas(a/p,b/p,p)%p;
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
    int k;
    cin>>n>>k;
    int ans=0;
    for (int i = 1; i <=n ; ++i) {
        ans=(ans+ Lucas(n/i-1,k-1,mod))%mod;
    }
    cout<<ans<<'\n';

    return 0;
}
posted on 2023-08-03 19:45  IR101  阅读(4)  评论(0编辑  收藏  举报  来源