2025“钉耙编程”中国大学生算法设计暑期联赛(5)

切排列

和第二场一样,映射

#include<iostream>
using namespace std;

const int N=200010;
int n;
int a[N];int mp[N];int b[N];

int main(){
    int T;cin>>T;
    while (T--)
    {
      cin>>n;
      for(int i=1;i<=n;i++){
        cin>>a[i];mp[a[i]]=i;
      }
      for(int i=1;i<=n;i++){cin>>b[i];b[i]=mp[b[i]];}
      
      int ans=0;
      for(int i=1;i<=n;i++){
        int j=i;
        while(j<=n&&b[j]==b[i]+j-i)j++;
        i=j-1;
        ans++;
      }
      cout<<ans<<'\n';
    }
    
}

最小值

#include <bits/stdc++.h>
//#define int long long 
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define fr first
#define se second
#define endl '\n'
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;

const int N = 2e5 + 10;

int n;
ll a[N], b[N], c[N],d[N];

void solve()
{
    cin >> n;
    for(int i = 1; i <= n; i ++){
        cin >> a[i];
    }
    for(int i = 1; i <= n; i ++){
        cin >> b[i];
        c[i] = a[i] - b[i];
        d[i]=a[i]+b[i];
    }
    sort(c + 1, c + 1 + n);sort(d+1,d+n+1);

    ll ans = INF;
    for(int i = 2; i <= n; i ++){
        ans = min(ans, c[i] - c[i - 1]);
        ans=min(ans,d[i]-d[i-1]);
    }
    cout << ans << endl;
}


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

随机反馈

K-mex

【遇到i特别大的情况】要想到杨辉三角,要求SIGMA(i*P(i))
=P(1)
+P(2)+P(2)
+P(3)+P(3)+P(3)
=SIGMA(P(mex>=i))

要求SIGMA(mex>=i)=SIGMA(C(n-i,k-i)/C(n,k))
【上面有i下面有i】放鞭炮,只有C(n,k-1)/C(n,k)

#include<iostream>
using namespace std;
#define ll long long
#define int long long
const ll mod=1e9+7;
ll n,k;
ll qmi(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1)res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
ll inv(ll x){
    return qmi(x,mod-2)%mod;
}
signed main(){
    int T;cin>>T;
    while (T--)
    {
        ll ans=0;
        cin>>n>>k;
        /*ll fac;
        for(int i=1;i<=k;i++){
            if(i==1){
                fac=(k*(n-k)%mod)%mod*(inv(n-1)*inv(n)%mod)%mod;
            }else fac=(fac*(k-i+1)%mod)*inv(n-i)%mod;
            ans=(ans+i*fac%mod)%mod;
            //ans=(ans+i*C(n-i-1,k-i)%mod)%mod;
        }
        //cout<<ans;
       // ans=ans*inv(C(n,k))%mod;
        cout<<ans<<'\n'; */
        //1.确定对的C O(klogk)
        //2.常数累乘fac O(klogk)
        //3.杨辉三角,上下都有i的放鞭炮
        cout<<k*inv(n-k+1)%mod<<'\n';
    }
    
}

四角洲行动

数据范围比较小,可以枚举O(100100100)
给的方块有拓扑序22 -> 13->12->11,这就可以后面推到的11和前面12,2*2没有关系

#include<bits/stdc++.h>
using namespace std;

/*
给的方块比较特殊吧
2*2如果不放2*2就只能放1*2和1*1,和两个1*2相同
1*3如果不放1*3就只能放1*2和1*1,或者1*1三个,和1*2和1*1相同
1*2如果不放1*2就只能放1*1和1*1,和两个1*1相同
*/
const int N=1010;
int ma,mb,mc,md;
int a[N],b[N],c[N],d[N];int na,nb,nc,nd;
bool cmp(int tx,int ty){
    return tx>ty;
}

int main(){
    std::ios::sync_with_stdio(false);
    int T;cin>>T;
    while(T--){
        cin>>ma>>mb>>mc>>md;
        cin>>na;for(int i=1;i<=na;i++)cin>>a[i];sort(a+1,a+na+1,cmp);for(int i=1;i<=na;i++)a[i]=a[i-1]+a[i];
        cin>>nb;for(int i=1;i<=nb;i++)cin>>b[i];sort(b+1,b+nb+1,cmp);for(int i=1;i<=nb;i++)b[i]=b[i-1]+b[i];
        cin>>nc;for(int i=1;i<=nc;i++)cin>>c[i];sort(c+1,c+nc+1,cmp);for(int i=1;i<=nc;i++)c[i]=c[i-1]+c[i];
        cin>>nd;for(int i=1;i<=nd;i++)cin>>d[i];sort(d+1,d+nd+1,cmp);for(int i=1;i<=nd;i++)d[i]=d[i-1]+d[i];

        int ans=0;
        int l11,l12,l13,l22,sum;
        for(int i=0;i<=min(nd,md);i++){//22
            l11=l12=l13=l22=0;sum=0;
            l12+=(md-i)*2;sum+=d[i];
            for(int j=0;j<=min(nc,mc+l13);j++){//13
                l12+=(mc+l13-j);l11+=(mc+l13-j);sum+=c[j];
                for(int k=0;k<=min(nb,mb+l12);k++){//12
                    l11+=2*(mb+l12-k);sum+=b[k];
                    
                    //11直接全放
                    sum+=a[min(na,ma+l11)];
                   
                    ans=max(ans,sum);

                    sum-=a[min(na,ma+l11)];
                    l11-=2*(mb+l12-k);sum-=b[k];
                }l12-=(mc+l13-j);l11-=(mc+l13-j);sum-=c[j];
            }l12-=(md-i)*2;sum-=d[i];
        }
        cout<<ans<<'\n';
    }
}

“合理”避税

数据好像有k0,除零错误了,(assert了不管用,if(k0)又另一种ce)

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=200010;
int n,m,k,p;
int a[N];
bool cmp(int tx,int ty){
    return tx%k > ty%k;
}

bool check(int mid){
    int cnt=0;//所有人能贡献的k的数量
    for(int i=1;i<=n;i++){
        if(a[i]>=mid*k){
            cnt+=mid;//最多就每天取k,多的不计
        }else {
            cnt+=a[i]/k;
        }
    }

    if(cnt>=mid*p){
        //全拿k
        return (mid*p*k>=m);
    }
    //有拿部分
    int sum=0;int now=0;
    for(int i=1;i<=n;i++){
        if(a[i]>=mid*k)continue;
        ++now;
        if(now>mid*p-cnt)break;
        sum+=a[i]%k;
    }
    return cnt*k+sum>=m;
}

signed main(){
int T;cin>>T;
while(T--){
    cin>>n>>m>>k>>p;
    for(int i=1;i<=n;i++)cin>>a[i];
    sort(a+1,a+n+1,cmp);
    int l=1;int r=m;
    while(l<r){
        int mid=(l+r)>>1;
        if(check(mid))r=mid;
        else l=mid+1;
    }
    cout<<l<<'\n';
}

}
posted @ 2025-08-03 11:29  arin876  阅读(90)  评论(0)    收藏  举报