7.10补题

CodeForces 1251A
一串字符,如果一个字母只有连续出现偶数次,则键盘上这个字母的键是坏的,输出键位没坏的字母(只算出现的字母)

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <iomanip>
#define INF 0x3f3f3f3f
#define mod 2008
using namespace std;
int b[27];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        string a;
        cin>>a;
        int n=a.size();
        if(n==1)
        {
            cout<<a<<endl;
            continue;
        }
        memset(b,0,sizeof(b));
        if(a[0]!=a[1]) b[a[0]-'a']=1;
        if(a[n-1]!=a[n-2]) b[a[n-1]-'a']=1;
        int k=1;
        for(int i=0;i<n-1;i++)
        {
            if(a[i]==a[i+1])
            {
                k++;
            }
            else
            {
                if(k%2) b[a[i]-'a']=1;
                k=1;
            }
        }
        if(k%2) b[a[n-1]-'a']=1;
        sort(a.begin(),a.end());
        for(int i=0;i<n;i++)
            if(b[a[i]-'a']==1)
        {
            cout<<a[i];
            b[a[i]-'a']=0;
        }
        cout<<endl;
    }
    return 0;
}

CodeForces 1251C
一串数字,如果相邻两位奇偶性不同则可交换,不限交换次数,求交换后最小的数。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <iomanip>
#define INF 0x3f3f3f3f
#define mod 2008
using namespace std;
char x[300010],y[300010];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        string a;
        cin>>a;
        int n=a.size();
        int ji=0,ou=0;
        for(int i=0;i<n;i++)
            if((a[i]-'0')%2)
        {
            ji++;
            x[ji]=a[i];
        }
        else
        {
            ou++;
            y[ou]=a[i];
        }
        int i=1,j=1;
        while(i<=ji||j<=ou)
        {
            if(i>ji)
            {
                cout<<y[j];
                j++;
            }
            else if(j>ou)
            {
                cout<<x[i];
                i++;
            }
            else if(x[i]<y[j])
            {
                cout<<x[i];
                i++;
            }
            else
            {
                cout<<y[j];
                j++;
            }
        }
        cout<<endl;
    }
    return 0;
}

核心思想是把数按顺序分成奇偶两类再一个一个输出

CodeForces - 1251B
给出n个01构成的字符串,每次顺便交换任意两个,问最多构成几个回文串。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <iomanip>
#define INF 0x3f3f3f3f
#define mod 2008
using namespace std;
#define SIS std::ios::sync_with_stdio(false)
int main()
{
    SIS;
    string s;
    int t;
    cin >> t;
    while(t--)
    {
        int n,a[2];
        bool flag=false;
        a[0]=0;
        a[1]=0;
        cin >> n;
        for(int i=0;i<n;i++)
        {
            cin >> s;
            int len=s.size();
            if(len&1) flag=true;
            for(int j=0;j<len;j++)
                a[s[j]-'0']++;
        }
        if(a[0]&1 && a[1]&1 && !flag) n--;
        cout << n << endl;
    }
    return 0;
}

奇数必定可以移动成回文,就算有偶数也可以通过与奇数的交换构成回文,唯一构不成回文的是:1和0 的个数都是奇数,且几个串的长度都是偶数。
n&1 就是判断bain是否为奇数,也可以写 n%2,原理是n为奇数时,对应bai的二进制数最低位一定为1,n&1的结果就是1,反之为偶,0。

CodeForces - 1251D
抛去背景就是给出n个区间的左右两端,从每个区间选定一个数,和不超过s,并且这几个数的中位数尽可能大,

#include<bits/stdc++.h>
using namespace std;
typedef long long i64;
const int maxn = 200002;
struct interval{
    int l, r;
    bool operator < (const interval &B)const{
        return l < B.l;
    }
}E[maxn];
bool ok(int target, int n, i64 S){
    i64 cost = 0;
    int cnt = 0;
    for(int i=n;i>=1;--i){
        if(cnt*2<n&&E[i].r>=target){
            if(E[i].l>=target)cost += E[i].l;
            else cost += target;
            cnt++;
        }else{
            cost += E[i].l;
        }
    }
    return cost<=S && cnt*2>n;

}
void work(){
    i64 S;
    int n;
    scanf("%d%lld", &n, &S);
    for(int i=1;i<=n;++i){
        scanf("%d%d", &E[i].l, &E[i].r);
    }
    sort(E+1, E+n+1);
    int L = E[n/2+1].l;
    int R = 1000000000;
    while(L<=R){
        int mid = (L+R)>>1;
        if(ok(mid, n, S))L = mid + 1;
        else R = mid - 1;
    }
    printf("%d\n", L-1);
}
int main(){
    int t;scanf("%d", &t);
    while(t--){
        work();
    }
    return 0;
}

中位数越大,发出的工资越多,用贪心判断是否有(n+1)/2个变量的值大于等于mid,

CodeForces - 1251E
有n个人投票,第i个人对应mi,pi,表示有mi投给你,他就投你,否则需要花费pi让他投你,求获得所有票最少需要多少钱

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 2e5 + 7;
int N;
vector<int> vt[maxN];
int main()
{
    int T; scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &N);
        for(int i=0; i<=N; i++) vt[i].clear();
        for(int i=1, m, p; i<=N; i++) 
        { 
            scanf("%d%d", &m, &p); 
            vt[m].push_back(p); 
        }
        priority_queue<int, vector<int>, greater<int>> Q;
        ll ans = 0;
        for(int i=N; i>=0; i--)
        {
            int len = (int)vt[i].size();
            for(int j=0; j<len; j++) 
                Q.push(vt[i][j]);
            while(Q.size() > N - i) 
            { 
                ans += Q.top(); 
                Q.pop(); 
                }
        }
        printf("%lld\n", ans);
    }
    return 0;
}

用优先队列,枚举所有的已选人数,满足与n差小于i说明偏大,偏大的花p买

CodeForces - 1251F
给出n块白板,k块红板,并给出高度a(白),b(红),在周长为q的情况下,使得任意数量的白和一块红组成两个数列递增,并使红板高度最大,求取法数量。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXN 1200010
using namespace std;
typedef long long LL;
const int mod=998244353;
int n,k,q,len,bit,rev[MAXN];
LL A[MAXN],B[MAXN],cnt[MAXN];
LL fac[MAXN],invi[MAXN],p2[MAXN];
LL ans[MAXN];

int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
    return x*f;
}

LL C(int n,int m) {
    if(m>n) return 0;
    return fac[n]*invi[m]%mod*invi[n-m]%mod;
}

LL qpow(LL x,LL k){
    LL res=1;
    while(k){
        if(k&1) res=res*x%mod;
        x=x*x%mod;
        k>>=1;
    }
    return res;
}

void NTT(LL *a,int opt){
    for(int i=0;i<len;i++)
        if(i<rev[i]) swap(a[i],a[rev[i]]);
    for(int mid=1;mid<len;mid<<=1){
        LL wn=qpow(3,(mod-1)/(mid*2));
        if(opt==-1) wn=qpow(wn,mod-2);
        for(int i=0;i<len;i+=mid*2){
            LL w=1;
            for(int j=0;j<mid;j++,w=w*wn%mod){
                LL x=a[i+j],y=w*a[i+j+mid]%mod;
                a[i+j]=(x+y)%mod,a[i+j+mid]=(x-y+mod)%mod;
            }
        }
    }
}

int main(){
    n=read();k=read();
    fac[0]=invi[0]=1;invi[1]=1;p2[0]=1;
    for(int i=2;i<=n;i++) invi[i]=invi[mod%i]*(mod-mod/i)%mod;
    for(int i=1;i<=n;i++) 
        fac[i]=fac[i-1]*i%mod,
        p2[i]=p2[i-1]*2%mod,
        invi[i]=invi[i]*invi[i-1]%mod;
    for(int i=1;i<=n;i++) cnt[read()]++;
    for(int i=1;i<=k;i++){
        int l=read();
        int na=0,nb=0;
        memset(A,0,sizeof(A));
        memset(B,0,sizeof(B));
        for(int i=l-1;i>0;i--) 
            if(cnt[i]>=2) nb+=2;
            else if(cnt[i]==1) na++;
        for(int i=0;i<=na;i++) A[i]=C(na,i)*p2[i];
        for(int i=0;i<=nb;i++) B[i]=C(nb,i);
        len=1,bit=0;
        while(len<=na+nb) len<<=1,bit++;
        for(int i=0;i<len;i++) rev[i]=((rev[i>>1]>>1) | ((i&1)<<(bit-1)));
        NTT(A,1);NTT(B,1);
        for(int i=0;i<len;i++) A[i]=A[i]*B[i]%mod;
        NTT(A,-1);
        LL inv=qpow(len,mod-2);
        for(int i=0;i<=na+nb;i++) A[i]=A[i]*inv%mod;
        for(int i=0;i<=na+nb;i++)
            (ans[(l+i+1)*2]+=A[i])%=mod;
    }
    q=read();
    while(q--) printf("%lld\n",ans[read()]);
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值