2020牛客寒假基础算法训练营4 D子段异或 前缀异或和 F dfs树上深度 B 括号匹配 C子段乘积 双指针/线段树 A找规律/斐波那契数列 E模拟字符串加法大数加

23 篇文章 0 订阅
20 篇文章 0 订阅

https://ac.nowcoder.com/acm/contest/3005#question
D
在这里插入图片描述
alar=sum[r]^sum[l-1]=0 1-r 1-l-1异或抵消前面相同的为l-r异或
mp[0]=1必须写

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
ll n,a[maxn],sum[maxn],ans;
map<ll,ll> mp;//2^30=1e9 该异或前缀和最大出现2e5次 
int main(){
	cin>>n;
	mp[0]++;//ai可以为0 
	for(int i=1;i<=n;i++){
		cin>>a[i];
		sum[i]=sum[i-1]^a[i];
		if(mp.count(sum[i])){	//sum[r]^sum[l-1]=0 有多少sum[l-1]与sum[r]相同的数字就有多少种异或为0的情况 
			ans+=mp[sum[i]];
		}
		mp[sum[i]]++;	//之前未出现过也++ 
	}
	
	cout<<ans<<endl;
	return 0;
}

F
牛牛胜 main函数中要写dfs(1,1)
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
ll n,a[maxn],fa,ans,cnt0,cnt1;
vector<ll> v[maxn];	//父亲在1-1e6内 
//距离为偶数 先手胜 == 2个深度为奇数的点距离为偶数 2个深度为偶数的点距离为偶数 
void dfs(ll x,ll dep){
	if(dep&1) cnt1++;
	else cnt0++;
	for(int i=0;i<v[x].size();i++)
		dfs(v[x][i],dep+1);
}
int main(){
	cin>>n;
	for(int i=2;i<=n;i++){
		cin>>fa;
		v[fa].push_back(i);
	}
	dfs(1,1);//根节点为1 深度为1 
	ans=cnt1*(cnt1-1)+cnt0*(cnt0-1);
	
	cout<<ans<<endl;
	return 0;
}

F 01染色

#include <algorithm>
#include <cmath>
#include <iostream>
#include <map>
#include <set>
#include <stack>
#include <vector>
 
const long long MOD = 1e9 + 7;
const int MAXN = 1e6 + 7;
 
std::vector<int> edge[MAXN];
std::vector<int> color(MAXN);
 
void dfs(int u, int c) {
  for (auto &v : edge[u]) {
    color[v] = c ^ 1;
    dfs(v, c ^ 1);
  }
}
 
int main() {
  int n;
  std::cin >> n;
  for (int i = 2; i <= n; ++i) {
    int x;
    std::cin >> x;
    edge[x].emplace_back(i);
  }
  color[1] = 0;
  dfs(1, 0);//染成0 深度为奇数的点 下一层染成1 深度为偶数的点 
 
  long long x1 = 0, x2 = 0;
  for (int i = 1; i <= n; ++i) {
    if (color[i]) {
      ++x1;
    } else {
      ++x2;
    }
  }
  std::cout << x1 * (x1 - 1) + x2 * (x2 - 1) << "\n";
  return 0;
}

B
在这里插入图片描述
栈为空扫到右括号 右括号多余
栈不空 左括号多余
栈顶左括号与当前扫到右括号不匹配 不弹栈 栈不空
不合法 右括号始终不进栈 左括号不出栈

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
const int mod=1e9+7;
#define mp make_pair
#define fi first
#define se second
ll t,n,m,k,ans;
ll a[maxn],f;
string s;
stack<char> st;
int main(){
    cin>>s;
    ll len=s.size();
    for(int i=0;i<len;i++){
        if(s[i]=='{' || s[i]=='[' || s[i]=='(')
            st.push(s[i]);
        else if((s[i]==']' || s[i]=='}' || s[i]==')') && st.empty()){
            f=1;
            break;
        }
        else if(s[i]=='}' && st.top()=='{')
                st.pop();
        else if(s[i]==']' && st.top()=='[')
                st.pop();
        else if(s[i]==')' && st.top()=='(')
                st.pop();
     
    }
    if(!st.empty())
        f=1;
    if(f)
        cout<<"No"<<endl;
    else
        cout<<"Yes"<<endl;
    return 0;
}

手写栈

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
ll n,a[maxn],ans,now,len,f;
char st[maxn];
string s;
int main(){
	f=1;
	cin>>s;
	len=s.size();
	for(int i=0;i<len;i++){
		if(s[i]=='[' || s[i]=='(' || s[i]=='{')
			st[++now]=s[i];
		else if(s[i]==']'){
			if(st[now]=='[')
				now--;
			else{	//不匹配 或 栈空右括号多余 
				f=0;
				break;
			}
		}
		else if(s[i]==')'){
			if(st[now]=='(')
				now--;
			else{
				f=0;
				break;
			}
		}
		else if(s[i]=='}'){
			if(st[now]=='{')
				now--;
			else{
				f=0;
				break;
			}
		}
	}
	if(f && now==0)	//栈空右括号不多余 括号匹配
		cout<<"Yes"<<endl;
	else
		cout<<"No"<<endl; 
	return 0;
}

C
在这里插入图片描述
取mod 998244353 ai值可以为0

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
const int mod=998244353;
#define mp make_pair
#define fi first
#define se second
ll t,n,m,k,ans,pos;
ll a[maxn],pre[maxn],vis[maxn];
string s;
ll ksm(ll a,ll b){
	ll res=1;
	while(b){
		if(b&1)
			res=res*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return res;
}
ll inv_mod(ll a){
	return ksm(a,mod-2);
}
int main(){
	cin>>n>>k;
	pre[0]=1;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	ll l=1,r=1,res=1;
	for(;r<=n;){
		if(a[r]==0)
		{
			l=r+1;
			r=l;
			res=1;
		
		}
		else{
			
			res=res*a[r]%mod;
			r++;
		}
		if(r-l==k){
			ans=max(ans,res);
	//		cout<<l<<" "<<r<<" "<<ans<<endl;
			res=res*inv_mod(a[l])%mod;
			l++;
			
		}
			
	}
	cout<<ans<<endl;
	return 0;
}

线段树

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
typedef long long ll;
const ll mod=998244353;
 
ll a[maxn];
int now;
 
class segment_tree {public:
    #define nd node[now]
    #define ndl node[now << 1]
    #define ndr node[now << 1 | 1]
     
    struct segment_node {
        int l,r;
        ll sum;
    }node[maxn << 2];
     
    void pushup(int now) {
        nd.sum = (ndl.sum * ndr.sum)%mod;
    }
     
    void maketree(int l,int r,int now = 1) {
        nd = {l,r,0};
        if(l == r) {
            nd.sum = a[l]; 
            return;
        }
        int mid = l + r >> 1;
        maketree(l,mid,now << 1);
        maketree(mid+1,r,now << 1 | 1);
        pushup(now);
    }
     
    ll query(int l, int r, int now = 1) {
        if(l<=nd.l && r>=nd.r) return nd.sum;
        ll res = 1;
        if(l <= ndl.r) res = (res*query(l,r,now << 1))%mod;
        if(r >= ndr.l) res = (res*query(l,r,now << 1 | 1))%mod;
        return res;//不能忘
    }
}tree;
 
int main(){
    int n,m,k;
    cin >> n >> k;
    for(int i=1;i<=n;i++) cin >> a[i];
    tree.maketree(1,n);
    ll ans=0;
    for(int i=1;i<=n-k+1;i++){
        ans=max(ans,tree.query(i,i+k-1));
    }
    cout << ans << endl;
    return 0;
}

A
运行速度快

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
const int mod=1e9+7;
#define mp make_pair
#define fi first
#define se second
ll t,n,m,k,ans;
ll a[maxn],f;
string s;
int main(){
	cin>>t;
	while(t--){
		ll x=0,y=0,t=0;
		cin>>n;
		if(n==0)
			cout<<1<<endl;
		else if(n==1)
			cout<<3<<endl;
		else
		{
			//2 1
			x=2,y=1;
			for(int i=2;i<=n;i++){
				t=y;
                y=x;
                x=x+t;
			
			}
			
			cout<<x+y<<endl;
		}
	}
	return 0;
}

斐波那契数列递推慢 a[n+2]+a[n+1]

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
const int mod=998244353;
#define mp make_pair
#define fi first
#define se second
ll t,n,m,k,ans,pos;
ll a[maxn],pre[maxn],vis[maxn];
string s;

int main(){
	a[1]=1;a[2]=1;
	for(int i=3;i<=82;i++)
		a[i]=a[i-1]+a[i-2];
	cin>>t;
	while(t--){
		cin>>n;
		if(n==0)
			cout<<1<<endl;
		else
			cout<<a[n+2]+a[n+1]<<endl;
	}
	return 0;
}

E
5e5长度的数字爆ll
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+5;
const int mod=998244353;
#define mp make_pair
#define fi first
#define se second
string s,ans;
char c[maxn];
ll cnt,p;

string num_push(string a,string b){
    ans.clear();
  int lena=a.size();
  int lenb=b.size();
  reverse(a.begin(),a.end());  //翻转a
  reverse(b.begin(),b.end());  //翻转b
  int yu=0;  //余数
  for(int i=0;;i++){    //一直跑
    if(i<lena&&i<lenb){    //如果小于a的长度,并且小于b的长度
      ans+=(yu+a[i]-'0'+b[i]-'0')%10+'0';  //第几位等于a的数值加上b的数值
      yu=(yu+a[i]-'0'+b[i]-'0')/10;  //然后再求余数
    }else if(i<lena){          //如果只小于a,说明b跑完了
      ans+=(yu+a[i]-'0')%10+'0';  //只需加上a的数值加上之前的余数
      yu=(yu+a[i]-'0')/10; 
    }else if(i<lenb){         
      ans+=(yu+b[i]-'0')%10+'0';
      yu=(yu+b[i]-'0')/10;
    }else if(yu!=0){   //都跑完了余数还不为零那么再进一位
      ans+=yu%10+'0';
      yu=yu/10;
    }else break; //然后退出
  }
  reverse(ans.begin(),ans.end());  //最后翻转一下
  return ans;
}
 
int main(){
    cin>>s;
    ll len=s.size();
    for(int i=0;i<len;i++){
        if(s[i]=='+')
            cnt++;
        else
            c[++p]=s[i];
    }
    sort(c+1,c+p+1);
//  for(int i=1;i<=p;i++)
//      cout<<c[i];
//  cout<<endl;
	if(cnt==0)	//0个+ 输出排序后的s 
	{
		for(int i=1;i<=p;i++){
			cout<<c[i];
		}
		cout<<endl;
		return 0;
	}
    ll num=p/(cnt+1);ll res=p%(cnt+1);
    ll num1=res,num2=(cnt+1)-num1;//num+1位num1g  num位num2个
      
    string t[cnt+1];
    ll n=0;
    for(int i=1;i<=num1;i++){
        for(int j=1;j<=num+1;j++){
            t[n]+=c[(j-1)*(cnt+1)+i];
        }
        n++;
    }
    for(int i=num1+1;i<=cnt+1;i++){
        for(int j=1;j<=num;j++){
            t[n]+=c[(j-1)*(cnt+1)+i];
        }
        n++;
    }
    ans=num_push(t[0],t[1]);
    for(int i=2;i<n;i++){
        ans=num_push(ans,t[i]);
    }
    cout<<ans<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值