B.小雷的神奇电脑
题目:
原题链接
给出量个数n,m,一个有n个数的数组,数组里每个数不超过2^m,求数组任意两个数同或后的最大值。同或定义:二进制下相同为1,不同为0。
思路:
观察同或的定义可以发现相邻的数同或得出的结果是最大的,所以我们需要先把数组排序,我先运用了异或的性质,用a[i]^a[i+1],求出异或后的最小值,然后再利用bitset把每一位都取反就是同或后的最大值。因为我定义的是31位数,所以需要把前len-m位数置0。最后转为10进制数就可以了。
AC代码:
#include <bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
const int N = 2e5 + 20;
int a[N], b[N], c[N];
//bitset<31> s;
int ans = INT_MAX;
signed main() {
IOS
int n, m, s = 0, x = 0, d;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
sort(a + 1, a + n + 1);
// for (int i = 1; i <= n; i++) {
// int tt = a[i];
// while (tt != 0) {
// //cout << "-1" << '\n';
// x = x * 10 + (tt % 2);
// tt = tt / 2;
// b[s]++;
// }
// //cout << x << '\n';
// if (b[s] != b[s - 1] && s != 1 && s != 0)
// break;
// s++;
// x = 0;
// c[i] = a[i];
// }
//cout << s << '\n';
for (int i = 1; i < n ; i++) {
d = a[i] ^ a[i + 1];
ans = min(ans, d);
}
bitset<31> q(ans);
q.flip();
string dd = q.to_string();
int len = dd.size();
for (int i = 0; i < len - m; i++)
dd[i] = '0';
//cout << dd << '\n';
int cnt = 0;
for (int i = 0; i < 31; i++) {
cnt = cnt * 2 + (dd[i] - '0');
//cout << dd[i] - '0' << " ";
}
cout << cnt << '\n';
}
C.岗位分配
题目:
原题链接
有众多志愿岗位需要被分配,给你志愿者人数和一个数组,数组中的值是每个地方至少要分配的人数,求可能的分配情况总数。
思路:
题目上说可以剩余,因为不管怎么分我们都要保证志愿岗位的最小志愿者人数,所以我们只需要讨论剩下的人怎么分配。
假设4个人需要分配到3个岗位中:
首先4可以分为(1,3),(2,2),(1,1,2),(4),如果是按照高中所学的隔板分配法,那么就是假设4个小球2个隔板,结果为 C_5^2=10;
这样我们明显是少了(1,3),(2,2)这两种含0的情况,所以我们要加上一个小球,令这个小球的价值为0,所以结果就是C_6^2=15。
这样,就可以得出:
0个人分配3个岗位 C_2^2=1
1个人分配3个岗位 C_3^2=3
2个人分配3个岗位 C_4^2=6
3个人分配3个岗位 C_5^2=10
4个人分配3个岗位 C_6^2=15
因此可以得出结论:
AC代码:
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e5+20;
const int mod=998244353;
int inv[N],fac[N];
//快速幂
int quick(int a,int b)
{
int ans=1;
while(b)
{
if(b&1)
ans=(ans*a)%mod;
b>>=1;
a=(a*a)%mod;
}
return ans;
}
void init()
{//求阶乘
fac[0]=1;
for(int i=1;i<N;i++)
fac[i]=fac[i-1]*i%mod;
//求逆元
inv[N-1]=quick(fac[N-1],mod-2);
for(int i=N-2;i>=0;i--)
inv[i]=inv[i+1]*(i+1)%mod;
}
int s(int n,int m)
{
if(m>n)
return 0;
if(m==0)
return 1;
return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
signed main()
{
IOS
init();
int n,m;
cin>>n>>m;
int sum=0;
for(int i=0;i<n;i++)
{
int a;
cin>>a;
m-=a;
}
int ans=0;
for(int i=0;i<=m;i++)
ans=(ans+s(n+i-1,n-1))%mod;
cout<<ans<<'\n';
}
D.简单的素数
题目:
原题链接
多实例,给出一个数x,是素数输出Yes,不是输出No。
思路:
签到题,暴力判断素数就可以了。
AC代码:
#include <bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
signed main() {
int t;
cin >> t;
while (t--) {
int x, f = 1;
cin >> x;
int k = sqrt(x);
for (int i = 2; i <= k; i++) {
if (x % i == 0) {
f = 0;
cout << "No" << '\n';
break;
}
}
if (f == 1)
cout << "Yes" << '\n';
}
}
F.小雷的算式
题目:
原题链接
给出一个只含加法的式子,把数字从大到小排序后输出,并输出结果。
思路:
我是首先把这个式子中含的每一个数用数组储存起来,然后从小到大排序后取反,输出出来。然后再把每一个数相加,输出结果。
AC代码:
#include <bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
const int N = 2e5 + 10;
int a[N];
signed main() {
IOS
string s;
cin >> s;
int x = 0, ans = 0;
int len = s.size();
for (int i = 0; i < len; i++) {
if (s[i] != '+')
a[x] = a[x] * 10 + (s[i] - '0');
if (s[i] == '+')
x++;
//cout << x << '\n';
}
sort(a, a + x + 1);
reverse(a, a + x + 1);
for (int i = 0; i < x; i++)
cout << a[i] << "+";
cout << a[x];
cout << '\n';
for (int i = 0; i <= x; i++)
ans += a[i];
cout << ans << '\n';
}
H.聪明且狡猾的恶魔
题目:
原题链接
给出一个数x代表金币数量,n代表恶魔数量。需要让50%及以上的恶魔利益最大,求最多可以获得多少金币。
思路:
要想获得最大金币数量,当恶魔数量为偶数时只需要满足50%,给(n/2)-1只恶魔一只一个金币,那自己所获得的金币数量就是x-(n/2)+1;当奇数时,需要让(n/2)+1只满意,需要给(n/2)只恶魔一只一个,此时金币数量是x-(n/2)。
AC代码:
#include <bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
signed main() {
IOS
int t;
cin >> t;
while (t--) {
int x, n;
cin >> x >> n;
if (n % 2 != 0)
cout << x - (n / 2) << '\n';
else
cout << x - (n / 2) + 1 << '\n';
}
}