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;
}