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;
}