A
思路
掌握 x^0=x 这个性质就可以秒了
题解
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n;
int k;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>k;
cout<<k<<' '<<0<<endl;
return 0;
}
B
思路
按照题目意思模拟即可
题解
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n;
int b[N];
int a[N];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=0;i<n;i++)cin>>a[i];
for(int i=1;i<n;i++)b[i]=a[i]^a[i-1];
int ans=b[1];
for(int i=2;i<n;i++)ans=__gcd(ans,b[i]);
cout<<ans<<endl;
return 0;
}
C
思路
猜结论,只要对角线放置就可以保证一次加2,又发现无论如何最后的sum之和都只会是偶数,于是猜测奇数的情况下无法构造,那么偶数只需要对角线摆放。
题解
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n;
int k;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>k;
if(k%2==1)cout<<-1<<endl;
else
{
int x = k/2;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(i==j&&i<x)cout<<1;
else cout<<0;
}
cout<<endl;
}
}
return 0;
}
D
思路
有点小麻烦,但是不难想出怎么做,主要难在模拟上了,看卡里有4种情况需要考虑11,12,22,21,实际上只需要考虑11,12,22就行,如我代码所示,最后是由结果可以是由22222...121212...1111 三部分构成,所以只会出现11,12,22三种情况,然后就是计算结果的方式了,显然22在一起可以使n-1的基础上+1,所以看代码模拟即可
题解
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n;
int k;
int cnt[3];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>k;
for(int i=0;i<n;i++)
{
int x;
cin>>x;
cnt[x]++;
}
int xx = k-n+1;
int minx=0;
if(cnt[1]+1>=cnt[2])minx = n-1;
else minx = n-1+(cnt[2]-cnt[1]-1);
int maxx = cnt[1]+(cnt[2]-1)*2;
// cout<<minx<<' '<<maxx<<endl;
if(k<minx||k>maxx)cout<<-1<<endl;
else
{
for(int i=0;i<=xx;i++)
{
cout<<2<<' ';
cnt[2]--;
}
for(int i=0;i<cnt[2];i++)
{
cout<<1<<' '<<2<<' ';
cnt[1]--;
}
for(int i=0;i<cnt[1];i++)
{
cout<<1<<' ';
}
cout<<endl;
}
return 0;
}
// 10 15
// 1 2 1 2 2 2 2 2 2 2
E
思路
考虑每一个节点的的所有的邻居的每一个二进制位分别进行计算0和1的个数,当中心节点的第i个二进制位为0,那么此时要使得无进制的三个数字累加最后结果是1,显然就是一个邻居节点为0,一个邻居节点为1的情况,所以此时的所有可能就是$$cnt =cnt0*cnt1$$,如果说中心节点的第i个二进制位为1,那么次数要使得最后三个数字的累加结果是1,显然就是两个邻居节点同时是0,或者两个邻居节点同时是1,次数的计算方式就是$$ cnt = C2_{cnt0}+C2_{cnt1}$$,最后计算ans就是将第i位代表的十进制数字×cnt累加取模即可
题解
#include <bits/stdc++.h>
const int N = 2e5+10;
const int mod = 998244353 ;
typedef long long ll;
using namespace std;
int n,m;
ll ans=0;
vector<int>graph[N];
int w[N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>w[i];
for(int i=0;i<m;i++)
{
int u,v;
cin>>u>>v;
graph[u].push_back(v);
graph[v].push_back(u);
}
for(int i=0;i<=30;i++)
{
ll xx = (1<<i);
ll cnt=0;
for(int j=1;j<=n;j++)
{
ll cnt0=0;
ll cnt1=0;
for(auto k:graph[j])
{
if((w[k]>>i)&1)cnt1++;
else cnt0++;
}
if((w[j]>>i)&1)
{
cnt = (cnt+(cnt0*(cnt0-1)/2)%mod + (cnt1*(cnt1-1)/2)%mod)%mod;
}
else
{
cnt = (cnt+cnt0*cnt1)%mod;
}
}
ll curans = (xx*cnt)%mod;
ans = (ans+curans)%mod;
}
cout<<ans<<endl;
return 0;
}
F
思路
动态规划求解,bool dp[i][j][k]表示前面i个数的最大公约数位j,此时的累加和为k是否成立,首先观察可知m的大小限制在1到50,所以我们可以考虑预处理1-50的约数,进入循环后,初始化dp和path数组,path数组用于保存每个节点的j,用于最后的有答案输出,那么接下来的部分看代码就能看懂了,三重循环遍历
题解
#include <bits/stdc++.h>
using namespace std;
const int N = 51;
const int MAX_X = 2501;
vector<int> divx[N];
bool dp[N][N][MAX_X];
int path[N][N][MAX_X];
int n,m,x;
void precom(int x)
{
for(int i=1;i<=x;i++)
{
for(int j=i;j<=x;j+=i)
{
divx[j].push_back(i);
}
}
}
int main()
{
int t;
cin>>t;
precom(50);
while(t--)
{
cin>>n>>m>>x;
memset(dp,false,sizeof(dp));
memset(path,0,sizeof(path));
for(int i=1;i<=m;i++){if(i<=x)dp[1][i][i]=true;}
for(int i=1;i<n;i++)
{
for(int j=1;j<=m;j++)
{
for(int k=1;k<=x;k++)
{
if(dp[i][j][k])
{
for(auto g:divx[j])
{
if(g+k<=x)
{
dp[i+1][g][g+k]=true;
path[i+1][g][g+k]=j;
}
}
}
}
}
}
int preg = -1;
for(int i=1;i<=m;i++)
{
if(dp[n][i][x])
{
preg=i;
break;
}
}
if(preg==-1)cout<<-1<<endl;
else
{
int curx=x;
int curg=preg;
vector<int>a(n+1);
for(int i=n;i>=1;i--)
{
a[i]=curg;
if(i>1)
{
preg = path[i][curg][curx];
curx = curx - curg;
curg = preg;
}
}
for(int i=1;i<=n;i++)cout<<a[i]<<' ';
cout<<endl;
}
}
}