A两数之和(枚举)
题意:输入一个正数z,找到两个不同的正整数x和y,使得x+y==z
分析:枚举x,y
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
int z;cin>>z;
for(int i=1;i<=z;i++){
for(int j=1;j<=z;j++){
if(i+j==z&&i!=j){
cout<<"YES"<<endl;
cout<<i<<" "<<j<<endl;
return 0;
}
}
}
cout<<"NO"<<endl;
}
B小红装匣子(模拟)
题意:a块1×2大小的物块,b块1×3大小的物块,能否填满2×n的匣子?能输出YES否则NO
分析:先判断b能放几块,直接让b从左往右放,上面也要放,且一行不能超过n/3块,所以b能放min(b/2,n/3),如果a大于剩下的地方则YES
代码;
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void sol(){
ll a,b,n;cin>>a>>b>>n;
b=b/2;b=min(b,n/3);
if(n-b*3<=a)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
int main(){
int t;cin>>t;
while(t--)sol();
return 0;
}
C小红的数字对对碰
题意:有一个长度为n的数组a,可以进行以下操作减少数组长度。
i<j且ai+aj<=0,则可消去ai和aj;i<j且ai^aj<=0,则可消去ai和aj。输出最小化后的数组长度
分析:一正一负或两个相等的数,异或<=0,先把正数相同的数消掉,用cnt记录出现奇数次的数字的个数。如果cnt大于负数个数,让cnt-负数个数,剩下的正数无法继续处理,如果cnt小于负数个数,让负数-cnt,剩下的负数内部消除。
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;cin>>n;int a[n+10];
for(int i=1;i<=n;i++)cin>>a[i];
map<int,int>mp;
int fs=0;
for(int i=1;i<=n;i++){
if(a[i]>=0)mp[a[i]]++;
else if(a[i]<0)fs++;
}
int cnt=0;
for(auto &x:mp){
if(x.second%2!=0)cnt++;
}
if(cnt>=fs)cout<<cnt-fs<<endl;
else cout<<(fs-cnt)%2<<endl;
}
D小红的最大字典序
题意:小红有n个数字和一个空字符串,现在进行n次操作:第i次操作将ai按照数位上的相对顺序,从左到右取出并依次插入s,想构造一个这样的字符串,使得字典序是所有合法构造中最大
分析:用大根堆,每次推入字符串,输出堆头的第一个字符,然后将推头的第一个字符移除
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;cin>>n;
priority_queue<string>q;
for(int i=0;i<n;i++){
string s;cin>>s;
q.push(s);
}
while(!q.empty()){
string ss=q.top();
q.pop();
cout<<ss.front();
if(ss.size()!=1)q.push(ss.substr(1));
}
}
E小红的图上加边(并查集)
题意:有一个n点m边的无向图,每个节点的权值是ai,每次连接的代价是新形成的连通块的最大元素的值,最小需要消耗多少代价可以把这个图连成连通的
分析:用并查集,每次遍历将祖先的权值更新为俩节点的祖先的权值的最大值。然后用ans将所有祖先的权值相加,减去最小祖先权值。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll a[N];
ll f[N];
ll zx(ll x){
if(f[x]==x)return x;//x没爸爸
else return f[x]=zx(f[x]);//找出爸爸的爸爸的。。
}
void h(ll x,ll y){
f[zx(y)]=zx(x);//x的最大祖先变成y最大祖先的爸爸;
}
int main(){
ll n,m;cin>>n>>m;ll ans=0,mi=0x3f3f3f3f;
ll u,v;
for(int i=1;i<=n;i++){
cin>>a[i];f[i]=i;
}
for(int i=1;i<=m;i++){
cin>>u>>v;
a[zx(v)]=max(a[zx(v)],a[zx(u)]);
a[zx(u)]=max(a[zx(v)],a[zx(u)]);
h(u,v);
}
for(int i=1;i<=n;i++){
if(zx(i)!=i)continue;
ans+=a[i];
mi=min(mi,a[i]);
}
cout<<ans-mi<<endl;
return 0;
}
F小红的括号串
题意:有多少种将?替换成左括号或右括号的方案,字符串可以循环移位,使得该字符串为合法的括号串。合法的括号串:左括号数量=右括号数量,俩俩相匹配。
分析:可以将左括号看出+1,右括号-1,只要前缀和总是>=0,它就是合法的括号串,由于可以循环移位,所以一定可以循环移位到一中前缀和全部>=0的。如果字符串长度为奇数,他的左括号和右括号永远不相等。所以我们把问号改成字符串左括号等于右括号即可,用二项式求出即可。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,mod=1e9+7;
ll f[N],invf[N];
ll ksm(ll a,ll b){
ll res=1%mod;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll inv(ll x){
return ksm(x,mod-2);
}
ll C(ll a,ll b){
return f[a]*invf[b]%mod*invf[a-b]%mod;
}
void init(){
f[0]=invf[0]=1;
for(int i=1;i<N;i++){
f[i]=f[i-1]*i%mod;
invf[i]=inv(f[i])%mod;
}
}
int main(){
ll n;cin>>n;ll kuohao=0;
string s;cin>>s;init();
if(n%2!=0){
cout<<"0"<<endl;
return 0;
}
ll cnt=0;
for(int i=0;i<s.size();i++){
if(s[i]=='(')kuohao++;
else if(s[i]==')')kuohao--;
else cnt++;
}
cout<<C(cnt,(kuohao+cnt)/2)<<endl;
return 0;
}