A. 小红的字符串切割
#include <bits/stdc++.h>
using namespace std;
int main()
{
string str;
cin>>str;
int len=str.length();
cout<<str.substr(0,str.length()/2)<<'\n';
cout<<str.substr(len/2);
}
B. 小红的数组分配
对原数组排序之后看每种数字的出现次数是否为偶数
#include <bits/stdc++.h>
using namespace std;
int v[200010];
int main()
{
int n;
cin>>n;
n*=2;
vector<int> a(n*2);
for(int i=1;i<=n;i++) cin>>v[i];
sort(v+1,v+n+1);
bool succ=true;
// for(int i=1;i<=n;i++) cout<<v[i]<<' ';
// cout<<'\n';
for(int i=1,j=2;j<=n;i+=2,j+=2) {
if(v[i]==v[j]) {
a[j/2]=v[i];
} else {
succ=false;
}
}
if(succ) {
for(int i=1;i<=n/2;i++)
cout<<a[i]<<' ';
cout<<'\n';
for(int i=1;i<=n/2;i++)
cout<<a[i]<<' ';
} else {
cout<<-1<<'\n';
}
return 0;
}
C. 小红关鸡
双指针,右指针不断向后移动,在保持两指针之间距离不超过 k 的前提下计算鸡窝个数最大值,个数越大概率越大。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ios::sync_with_stdio(false),cin.tie(0);
ll n,k;
cin>>n>>k;
vector<ll> v(n);
for(int i=0;i<n;i++) cin>>v[i];
sort(v.begin(),v.end());
ll left=0,right=0;
ll mx=0;
while(right<=n) {
mx=max(mx,right-left+1);
right++;
while(v[right]-v[left]>k) left++;
}
cout<<((double)mx/n)<<'\n';
return 0;
}
D. 小红的排列构造
读入数字时做处理
- 当数字 x 大小超过 n ,直接记录下当前位置,x 不用记录
- 当 x 第一次出现时,标记 x
- 当 x 出现且被标记过,说明出现了不止一次,记下当前位置
对于所有记下的位置和 1 ~ n 中没有出现过的数字,对应输出即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
bool st[100010];
int main()
{
ios::sync_with_stdio(false),cin.tie(0);
int n;
cin>>n;
vector<int> v;
for(int i=0;i<n;i++) {
ll x;
cin>>x;
if(x>n||st[x]) v.push_back(i);
else st[x]=true;
}
ll idx=0;
cout<<v.size()<<'\n';
for(int i=1;i<=n;i++) {
if(st[i]==false) {
cout<<(v[idx++]+1)<<' '<<i<<'\n';
}
}
return 0;
}
E. 小红的无向图构造
给出 n 个点,若要形成图,则至少需要 n - 1 个节点,维护每个距离的点的集合,对于距离为 i 的集合,集合中的每个点至少与上一层(距离为 i - 1)集合中某个点之间存在一条边,最少需要构造的边为当前集合中点的个数。若边还有剩余,可以向上一层多连边,或者本层点之间互相连边。
红色-必须要连的边
绿色-本层向上一层可以连的更多的边
黄色-本层节点之间可以连多余的边
当出现以下情况时,说明无解
- 边数量不足 n-1
- 边数量过多
- 节点距离出现断层,如0 1 1 3 3
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
vector<int> v[100010]; // 存上一层的点
vector<pii> ans;
map<int,int> mp;
ll n,m;
int main()
{
ios::sync_with_stdio(false),cin.tie(0);
cin>>n>>m;
vector<pii> a(n);
for(int i=0;i<n;i++) {
ll v;
cin>>v;
mp[v]++;
a[i]={v,i+1};
}
sort(a.begin(),a.end());
ll mne=0,last=-1; // 最少需要的边
bool flag=true;
for(auto [x,y]:mp) { // x-点的编号,y-点的数量
if(x!=last+1) {
flag=false;
break;
} else {
if(last!=-1) mne+=y;
}
last=x;
}
flag=flag&&(mne<=m);
if(flag) {
ll more=m-mne;
for(int i=0;i<n;i++) {
v[a[i].first].push_back(a[i].second);
}
for(int i=1;i<n;i++) {
for(int j=0;j<v[i].size();j++) {
ans.push_back({v[i-1][0],v[i][j]});
}
if(more) {
for(int k=1;k<v[i-1].size();k++) {
for(int j=0;j<v[i].size();j++) {
ans.push_back({v[i-1][k],v[i][j]});
more--;
if(more==0) break;
}
if(more==0) break;
}
}
if(more) {
for(int j=0;j<v[i].size();j++) {
for(int k=j+1;k<v[i].size();k++) {
ans.push_back({v[i][j],v[i][k]});
more--;
if(more==0) break;
}
if(more==0) break;
}
}
}
if(more) {
cout<<-1;
} else {
for(auto [x,y]:ans) {
cout<<x<<' '<<y<<'\n';
}
}
} else {
cout<<-1;
}
}
F、G. 小红的子序列权值和
看了大佬的题解点我
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll fact[100010],infact[100010],number[4];
ll n;
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;
}
void init(int n)
{
fact[0]=infact[0]=1;
for(int i=1;i<=n;i++) {
fact[i]=fact[i-1]*i%mod;
infact[i]=(ll)infact[i-1]*qmi(i,mod-2)%mod;
}
}
ll c(ll n,ll m)
{
if(m<0||n-m<0) return 0;
return fact[n]*infact[m]%mod*infact[n-m]%mod;
}
ll getsum(ll x)
{
ll res=0;
for(int i=0;i<=x;i++) {
res+=c(x,i)*(i+1)%mod;
res%=mod;
}
return res;
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0);
cin>>n;
init(n);
while(n--) {
int x;
cin>>x;
number[x]++;
}
ll ans=getsum(number[2])*getsum(number[3])%mod;
ans=ans*qmi(2,number[1])%mod;
ans--;
cout<<ans<<'\n';
return 0;
}