cf div3 970

A. 

 如果数量为偶数则能两两抵消,考虑先把数量为2的先抵消,如果有剩余的,看1个的个数能不能满足

#include<bits/stdc++.h>
using namespace std;

#define int long long
#define endl '\n'
const int N = 5e5 + 10;
const int mod = 1e9 + 7;
using namespace std;

void solve()
{
   int a,b;
   cin>>a>>b;
   b=b%2;
   a-=b*2;
   if(a%2||a<0)
   {
   		cout<<"NO"<<endl;
	} 
	else
	cout<<"YES"<<endl;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

 B.

 直接模拟即可

#include<bits/stdc++.h>
using namespace std;

#define int long long
#define endl '\n'
const int N =1e3+10;
const int mod = 1e9 + 7;
using namespace std;
char a[N][N];
void solve()
{
   int n;
   string s;
   cin>>n>>s;
   int k=sqrt(n);
   if(k*k!=n)
   {
   	cout<<"NO"<<endl;
   	return ;
   }
   s=' '+s;
   int l=0;
   int f=0;
   for(int i=1;i<=k;i++)
   {
   		for(int j=1;j<=k;j++)
   		{
   			a[i][j]=s[++l];
   			if(i==1||j==1||i==k||j==k)
   			{
   				if(a[i][j]=='0')
   				{
   					cout<<"NO"<<endl;
   					return ;
				   }
				   
			   }
			   else
			   {
			   	if(a[i][j]=='1')
			   	{
			   		cout<<"NO"<<endl;
			   		return ;
				   }
			   }
		   }
   }
   cout<<"YES"<<endl;
   
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

 C.

本题的范围不大,且样例已经给出了极限范围,直接l到r遍历就行

#include<bits/stdc++.h>
using namespace std;

#define int long long
#define endl '\n'
const int N =1e3+10;
const int mod = 1e9 + 7;
using namespace std;
char a[N][N];
void solve()
{
   int l,r;
   cin>>l>>r;
   int cnt=1;
   int k=1;
   while(l<=r)
   {
   		l+=k;
   		k++;
   		cnt++;
   }
   cout<<cnt-1<<endl;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

D.

有题意可知如果他们能相互遍历到,那么他们能遍历到0的个数都是相同的,我们可以用并查集将能相互遍历的连成一块,这样一块只要一次dfs就可以解决

#include<bits/stdc++.h>
using namespace std;

#define int long long
#define endl '\n'
const int N =2e5+10;
const int mod = 1e9 + 7;
using namespace std;
int a[N];
int b[N];
bool p[N];
int n;
string s;
int c[N],cnt=0;;
map<int,int> q;
int find(int x)
{
	if(x!=b[x])
	{
		b[x]=find(b[x]);
	}
	return b[x];
}
void dfs(int k,int fa)
{
	if(p[k])
	return ;
	p[k]=true;
	b[find(k)]=find(fa);
	dfs(a[k],fa);
	
}
void dfs1(int k)
{
	if(p[k])
	return ;
	if(s[k]=='0')
	cnt++;
	p[k]=true;
	dfs1(a[k]);
}
void solve()
{
   	cin>>n;
   	for(int i=1;i<=n;i++)
   	{
   		cin>>a[i];
   		p[i]=false;
   		b[i]=i;
	}
	
	cin>>s;
	s=' '+s;
	for(int i=1;i<=n;i++)
	{
		if(!p[i])
		{
			
			dfs(i,i);
		}
	}
	q.clear();
	memset(p,false,sizeof p);
	for(int i=1;i<=n;i++)
	{
		int k=find(i);
	//	cout<<k<<" ";
		if(q[k]==0)
		{
			cnt=0;
			dfs1(k);
			q[k]++;
			c[k]=cnt;
		}
		c[i]=c[k];
	}
	for(int i=1;i<=n;i++)
	{
		cout<<c[i]<<" ";
	}
	cout<<endl;
	
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

E.

题目要求是使奇数位置和偶数位置的字符都相同,那么我们要修改,当然要在原来相同字符最多的基础上修改它,这样才能使次数最小。

当n是偶数时,显然我们只要找到奇数位和偶数位各自出现最多的字符数量就行了,答案就是n减去两个最大值

当n是奇数时,我们必须要删一个,考虑删那一个能得到最优解呢,因为如果删了一个字符,那么这个字符之后的字符奇偶性就会发生转变,也就是说原来奇数位置的字符会变成偶数位置的字符。

知道了这一点,我们遍历从n到1每一个字符,考虑删去它后的影响,我们可以用两个数组然统计删除字符ai后1到i-1的26个小写字母数量,和i+1到n的26的小写字母数量,然后让对应的奇偶位置的加起来,求奇数和偶数位置的各自出现小写字母数量的最大值。

#include<bits/stdc++.h>
using namespace std;

#define int long long
#define endl '\n'
const int N =2e5+10;
const int mod = 1e9 + 7;
using namespace std;
int a[5][30],b[5][30];
void solve()
{
   	int n;
   	string s;
   	cin>>n>>s;
   	int cnt=0;
   	s=' '+s;
   	memset(a,0,sizeof a);
   	memset(b,0,sizeof b);
   	int k1=0,k2=0;
   	for(int i=1;i<=n;i++)
   	{
   			int c=s[i]-'a';
   			if(i%2==1)
   			{
   				a[0][c]++;
   				k1=max(k1,a[0][c]);
			}
			else
			{
				a[1][c]++;
				k2=max(k2,a[1][c]);
			}
			
	}
   	if(n%2==0)
   	{
   	
		cout<<(n-k1-k2)<<endl;
	}
	else
	{
		
		int mx=0;
		for(int i=n;i>=1;i--)
		{
			int k1=0,k2=0;
			int c=s[i]-'a';
			if(i%2)
			a[0][c]--;
			else
			a[1][c]--;
			for(int j=0;j<26;j++)
			{
				int x=a[0][j],y=a[1][j];
				x+=b[1][j];
				y+=b[0][j];
				k1=max(k1,x);
				k2=max(k2,y);
			}
		//	cout<<k1<<" "<<k2<<endl;
			mx=max(mx,k1+k2);
			if(i%2==1)
			b[0][c]++;
			else
			b[1][c]++;
		}
		
		cout<<n-mx<<endl;
	}
	
	
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

F.

这题感觉就是一个裸分数取模的题。注意取模,不然会wr

#include<bits/stdc++.h>
using namespace std;

#define int long long
#define endl '\n'
const int N =2e5+10;
const int mod = 1e9 + 7;
using namespace std;
int a[N];
int sum[N];
int sqow(int x,int y)
{
	int sum=1;
	while(y)
	{
		if(y&1)
		{
			sum=(sum*x)%mod;
		}
		y=y>>1;
		x=(x*x)%mod;
	}
	return sum%mod;
}
void solve()
{
   	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	sum[n+1]=0;
	for(int i=n;i>=1;i--)
	{
		sum[i]=(sum[i+1]+a[i])%mod;
	}
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		int k1=a[i]%mod,k2=sum[i+1]%mod;
		ans+=(k1*k2)%mod;
		ans=(ans)%mod;
	}
	int cnt=n*(n-1)/2;
	cnt=(cnt)%mod;
	int k=__gcd(ans,cnt);
	ans/=k;
	cnt/=k;
	int u=(ans*sqow(cnt,mod-2))%mod;
	cout<<u<<endl;
	
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

G.

G题也很好想,根据裴蜀定理我们始终能得到最小公倍数的任意倍数,所以先对整个a数组求一遍gcd得到数组a的最小公倍数x,但是我们要求第k位置的最大mex,其实这个问题可以变成在a数组中的元素可以为任意x的倍数(正的),求a中第k个未出现非负数的最大值。

那么我们就将a中的元素尽量都取小,为什么要尽量取小呢,那么想,如果这个元素在a数组中出现了,那么未出现是不是要比他大,所以要想让小元素的填满数组。

这题最好不要去直接计算,本菜鸡wr4发qaq,我觉得最好用答案二分一下,找到刚好第k个值就行。

#include<bits/stdc++.h>
using namespace std;

#define int long long
#define endl '\n'
const int N =2e5+10;
const int mod = 1e9 + 7;
using namespace std;
int a[N],b[N];
int x;
int n,k;
bool check(int mid)
{
	int g=mid/x+1;
	int y=mid-min(n,g)+1;
	if(y>=k)
	return true;
	return false;
}
void solve()
{
   	cin>>n>>k;
   	
   	for(int i=1;i<=n;i++)
   	{
   		cin>>a[i];
	}
	x=a[1];
	for(int i=2;i<=n;i++)
	{
		x=__gcd(x,a[i]);
	}
	if(n==1)
	{
		if(a[1]>=k)
		{
			cout<<k-1<<endl;
		}
		else
		{
			cout<<k<<endl;
		}
		return ;
	}
	if(x==1)
	{
		cout<<n+k-1<<endl;
	}
	else
	{
		int l=1,r=n+k+1,mid;
		int ans=0;
		while(l<=r)
		{
			int mid=(l+r)>>1;
			if(check(mid))
			{
				ans=mid;
				r=mid-1;
			}
			else
			l=mid+1;
		}
		cout<<ans<<endl;
	}
	
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值