河南萌新联赛2024第(三)场:河南大学

1.F 累加器

原题链接

1.题意

给你两个数 x,y,每次可以对x加一,可以加y次,此时x在二进制下有一些位发生改变,总共有多少位发生过改变,例如,0001加一后变成0010,有两位发生改变

2.思路

刚开始想用bitset求每个状态改变时,有多少个1,就是想求状态改变时与原来相比有哪几位发生了改变,但后来发现不对。其实我们发现可以对每个状态改变时求异或,比如,0001和0010求异或为0011,有两个1,确实有两位发生了改变。为什么可以这样算,因为求异或就是求加1后,有多少位改变,如果两个位相同则为0,如果不相同则为1,那么加1后可以对之前未改变时求异或

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2e6+5;
bitset<10000> a;
int b[N+10];
void js(){
	for(int i=1;i<=N;i++){
		a=i^(i+1);
		b[i]=b[i-1]+a.count(); //用一个前缀和来记录从1到i发生了多少次改变
	}
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int t;
	cin>>t;
	js(); //进行预处理
	while(t--){
		int x,y;
		cin>>x>>y;
		
		cout<<b[y+x-1]-b[x-1]<<endl; //因为加y次后,数值会变成x+y,
	}                  //用b[x+y-1]-b[x-1]即可,至于为什么减一模拟一下就知道了
} 

2.J keillempkill学姐の卷积

1.题意

给你两个矩阵,一个大矩阵n* n型,一个小矩阵m* m型,让小矩阵不断遍历大矩阵,将小矩阵下的元素与大矩阵对应位置的元素相乘,然后将所有乘积相加,得到结果矩阵的一个元素,最后输出这个结果矩阵(m-n+1)

2.思路

可以用4个循环模拟,i+k-1,j+l-1,代表大矩阵当前元素,同时,c[i][j]要+=,因为小矩阵所有的乘积和为结果矩阵的一个元素

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int a[25][25],b[25][25],c[50][50];
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int m,n;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>a[i][j];
		}
	}
	for(int i=1;i<=m;i++){
		for(int j=1;j<=m;j++){
			cin>>b[i][j];
		}
	}
	int w=0,p=0;
	for(int i=1;i<=(m-n+1);i++){
		for(int j=1;j<=(m-n+1);j++){
			for(int k=1;k<=n;k++){
				for(int l=1;l<=n;l++){
					c[i][j]+=a[k][l]*b[i+k-1][j+l-1];
				}
			}
		}
	}
  for(int i=1;i<=(m-n+1);i++){
  	for(int j=1;j<=(m-n+1);j++){
  		cout<<c[i][j]<<' ';
	  }
	  cout<<endl;
  }
} 

3.E 区间

例题链接

1.题意

在一个长度为n的纸带上,初始时所有位置颜色为白色,现在要执行以下两种操作一共q次

操作一:输入一个下标x,你需要将位置xxx的颜色翻转(白色变为黑色,黑色变为白色)

操作二:输入两个正整数L,R你需要输出区间[[L,R]中的连续的白色区间长度最大值

 void solve()
{
     int n,q,op,L,R,x;
     vector<int> v;
     cin>>n>>q;
     while(q--)
     {
         cin>>op;
         if(op==1)
         {
             cin>>x;
             auto t=lower_bound(v.begin(),v.end(),x);
             if(t!=v.end()&&*t==x)
             v.erase(t);
             else
             v.insert(t,x);
         }
         else
         {
             cin>>L>>R;
             auto t=lower_bound(v.begin(),v.end(),L);
             if(t==v.end()||*t>R)
             cout<<R-L+1<<'\n';
             else
             {
                 int k=*t,ans=*t-L;
                 t++;
                 while(t!=v.end()&&*t<=R)
                 {
                     ans=max(ans,*t-k-1);
                     k=*t;
                     t++;
                 }
                 ans=max(ans,R-k);
                 cout<<ans<<'\n';
             }
         }
     }   
}
signed main()
{
    IOS
    int t; 
    t=1;
    while(t--)
    solve();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值