2022河南萌新联赛第(六)场:郑州大学ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛牛客竞赛OJ (nowcoder.com)

2022河南萌新联赛第(六)场:郑州大学ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛牛客竞赛OJ (nowcoder.com)

1.A-想要更多的0_2022河南萌新联赛第(六)场:郑州大学 (nowcoder.com)

A-想要更多的0_2022河南萌新联赛第(六)场:郑州大学 (nowcoder.com) - silky__player - 博客园 (cnblogs.com)

单独写了一篇,因为对如何找[0,n]区间出现一个数字的次数不是特别清楚

2.B-求四边形内一点_2022河南萌新联赛第(六)场:郑州大学 (nowcoder.com)

稍微演算一下就好

#include<bits/stdc++.h>
using namespace std;
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define feh(i,x,y) for(int i=x;i>=y;i--)
#define int long long
#define pb push_back
#define IOS cin.tie(0)->sync_with_stdio(false);
#define inf 0x7fffffff
#define endl "\n"
/*
*/
signed main(){
double  x1,y1,x2,y2;
cin>>x1>>x2>>y1>>y2;
double k=(y2-y1)/(x2-x1);
double x=(x1*y1+x2*y2)/(k*(x1+x2)+y1+y2);
cout<<x<<" "<<k*x<<endl;
return 0;
}

3.C-盲打_2022河南萌新联赛第(六)场:郑州大学 (nowcoder.com)

这看代码应该就可以理解

#include<bits/stdc++.h>
using namespace std;
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define feh(i,x,y) for(int i=x;i>=y;i--)
#define int long long
#define pb push_back
#define IOS cin.tie(0)->sync_with_stdio(false);
#define inf 0x7fffffff
#define endl "\n"
/*
*/
string s[4];
int tt;
signed main(){
s[1]=" qwertyuiop";
s[2]=" asdfghjkl";
s[3]=" zxcvbnm";
cin>>tt;
while(tt--){
string t;
cin>>t;
for(auto now:t){
if(now>='A'&&now<='Z'){
cout<<"3 1 ";
now=now-'A'+'a';
}
for(int i=1;i<=3;i++){
for(int j=1;j<s[i].size();j++){
if(s[i][j]==now){
cout<<i<<" "<<j<<endl;
}
}
}
}
}
return 0;
}

4.D-树上祖先询问_2022河南萌新联赛第(六)场:郑州大学 (nowcoder.com)

提供两种写法

1.lca

直接考虑求a集合的lca看在b集合中是否存在a集合的lca,注意1不能是1的祖先.

#include<bits/stdc++.h>
using namespace std;
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define feh(i,x,y) for(int i=x;i>=y;i--)
#define ll long long
#define pb push_back
#define IOS cin.tie(0)->sync_with_stdio(false);
#define inf 0x7fffffff
#define endl "\n"
/*
就是dfs序和top如果b集合中存在一个点时a中所有集合所有点的lca即可
*/
const int N=1e5+100;
int son[N],fa[N],sz[N],d[N],top[N],n,q;
vector<int>b[N];
int s1[20],s2[20];
void dfs1(int x,int f){
sz[x]=1;
d[x]=d[f]+1;
son[x]=0;
for(auto i:b[x]){
if(i==fa[x]){
continue;
}
dfs1(i,x);
sz[x]+=sz[i];
if(sz[son[x]]<sz[i]) son[x]=i;
}
}
void dfs2(int x,int topx){
top[x]=topx;
if(son[x]) dfs2(son[x],topx);
for(auto i:b[x]){
if(i!=fa[x]&&i!=son[x]){
dfs2(i,i);
}
}
}
int lca(int x,int y){
while(top[x]!=top[y]){
if(d[top[x]]>=d[top[y]]){
x=fa[x];
}
else y=fa[y];
}
if(d[x]>d[y])
swap(x,y);
return x;
}
signed main(){
IOS
cin>>n>>q;
for(int i=2;i<=n;i++){
cin>>fa[i];
b[fa[i]].pb(i);
}
dfs1(1,0);
dfs2(1,1);
//cout<<lca(1,1)<<endl;
while(q--){
int x,y;
cin>>x>>y;
fel(i,1,x) cin>>s1[i];
fel(i,1,y) cin>>s2[i];
int tot=s1[1],flag=0;
fel(i,2,x)  tot=lca(tot,s1[i]);
fel(i,1,x){
if(tot==s1[i]) flag=1;//本题中lca不能为自己
}
if(flag){
if(tot==1){
cout<<"no"<<endl;
continue;
}
else tot=fa[tot];
}
flag=0;
fel(i,1,y){
           int t=lca(s2[i],tot);
           if(s2[i]==t) flag=1;//可能我是lca的祖先
}
if(flag) cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
return 0;
}

2.题解区大佬都解法

考虑dfs序。开两个数组din和dout,din存刚到这个点的cnt,dout存把他子树循环完的cnt。很明显一个点的din小于他子数所有点,dout大于他子树所有点。所以只要b集合中有一个点的din都小于a集合中的din,dout都大于a集合中的dout.

#include<bits/stdc++.h>
using namespace std;
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define feh(i,x,y) for(int i=x;i>=y;i--)
#define ll long long
#define pb push_back
#define IOS cin.tie(0)->sync_with_stdio(false);
#define inf 0x7fffffff
#define endl "\n"
/*
*/
const int N=1e5+100;
vector<int>b[N];
int n,q,din[N],dout[N],cnt;
void dfs(int x){
din[x]=++cnt;
for(auto i:b[x]){
dfs(i);
}
dout[x]=++cnt;
}
signed main(){
   IOS
cin>>n>>q;
fel(i,2,n){
int fa;
cin>>fa;
b[fa].pb(i);
}
dfs(1);
while(q--){
int t1,t2,t,mx=-1,mi=inf,flag=0;
cin>>t1>>t2;
fel(i,1,t1){
cin>>t;
mx=max(dout[t],mx);
mi=min(din[t],mi);
}
fel(i,1,t2){
cin>>t;
if(din[t]<mi&&dout[t]>mx){
flag=1;
}
}
cout<<(flag==1?"yes":"no")<<endl;
}
return 0;
}

5.F-取石子 ,但是作弊_2022河南萌新联赛第(六)场:郑州大学 (nowcoder.com)

因为只有1000堆石头,并且石头个数小于1000,所以我们可以直接考虑枚举取石头个数和放的堆.考虑到一个数异或本身等于0。任何一个数异或0都等于他本身,异或满足交换律。放到另外一堆的操作就很简单了。

#include<bits/stdc++.h>
using namespace std;
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define feh(i,x,y) for(int i=x;i>=y;i--)
#define int long long
#define pb push_back
#define IOS cin.tie(0)->sync_with_stdio(false);
#define inf 0x7fffffff
#define endl "\n"
/*
*/
int n;
int a[1100];
signed main(){
cin>>n;
fel(i,1,n) cin>>a[i];
int sum=0;
fel(i,2,n) sum^=a[i];
int ans=inf;
for(int i=0;i<a[1];i++) {
for(int j=2;j<=n;j++){
if((sum^a[j]^(a[1]-i)^(a[j]+i))==0){
//cout<<i<<" "<<j<<endl;
ans=min(ans,i);
}
}
}
cout<<(ans==inf?-1:ans)<<endl;
return 0;
}

6.H-数列求和_2022河南萌新联赛第(六)场:郑州大学 (nowcoder.com)

#include<bits/stdc++.h>
using namespace std;
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define feh(i,x,y) for(int i=x;i>=y;i--)
#define int long long
#define pb push_back
#define IOS cin.tie(0)->sync_with_stdio(false);
#define inf 0x7fffffff
#define endl "\n"
/*
*/
const int mod=1e11+3,N=1e7+10;
int f[N],n;
signed main(){
   IOS
cin>>n;
f[1]=1,f[2]=3;
fel(i,3,n) f[i]=(f[i-1]+f[i-2])%mod;
int sum=0;
for(int i=1;i<=n;i++){
sum=(sum+f[i])%mod;
}
cout<<sum%mod;
   return 0;
}

7.K-魔法数_2022河南萌新联赛第(六)场:郑州大学 (nowcoder.com)

只有五个约数,考虑到明显只能是五个质数,因为如果是其他数字,是可以拆开的,形成更多因子。1,x,x^2,x^3,x^4。所以就一个区间内的魔法数直接求开两次根号求区间内素数个数即可。

#include<bits/stdc++.h>
using namespace std;
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define feh(i,x,y) for(int i=x;i>=y;i--)
#define int long long
#define pb push_back
#define IOS cin.tie(0)->sync_with_stdio(false);
#define inf 0x7fffffff
#define endl "\n"
/*
*/
bool prime(int x){
if(x==1) return false;
for(int i=2;i*i<=x;i++){
if(x%i==0) return false;
}
return true;
}
int sum(int n){
int ans=0;
int t=sqrt(sqrt(n));
for(int i=1;i<=t;i++){
if(prime(i)) ans++;
}
return ans;
}
signed main(){
int t;
cin>>t;
while(t--){
int l,r;
cin>>l>>r;
cout<<sum(r)-sum(l-1)<<endl;
}
return 0;
}

8.L-字符串_2022河南萌新联赛第(六)场:郑州大学 (nowcoder.com)

这个题很明显是求循环结的长度,然后循环节的倍数都可以。求循环结主要是用kmp这个是kmp比较常用的地方。

#include<bits/stdc++.h>
using namespace std;
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define feh(i,x,y) for(int i=x;i>=y;i--)
#define int long long
#define pb push_back
#define IOS cin.tie(0)->sync_with_stdio(false);
#define inf 0x7fffffff
#define endl "\n"
/*
   只需要判断四块是否相等就好
   还有等于n的情况肯定是可以的0
   求最新小的循环结,然后他的倍数都是可以的
   感觉因该是这么写的
   求循环结用什么呢?
   kmp
*/
const int N=2e6+100;
int n;
string s;
int ne[N];
signed main(){
   IOS
cin>>n>>s;
s=" "+s;
for(int i=2,j=0;i<=n;i++){
while(j&&s[i]!=s[j+1]) j=ne[j];
if(s[i]==s[j+1]) j++;
ne[i]=j;//ne数组求的求得其实就是每个
}
int x=n-ne[n];//这个就是最小循环结点得长度
if(n%x) cout<<1<<endl;
else cout<<n/x<<endl;
return 0;
}
 

 

posted @   silky__player  阅读(57)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示