B、Rinne Loves Xor
大概就是一个数字分别异或一些数字的结果的和 等于 一个数字异或这些数字的和
然后就跑一下前缀和,遍历一遍就做完了
#include <bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
using namespace std;
ll a[100005][32];
ll b[100005][32];
const ll mod = 1e9 + 7;
int main()
{
	int n;
	sc("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		ll t;
		sc("%lld", &t);
		for (int j = 0; j < 32; j++)
		{
			if (t & (1LL << j))
				a[i][j] = 1;
			a[i][j] += a[i - 1][j];
		}
	}
	for (int i = 1; i <= n; i++)
	{
		ll t;
		sc("%lld", &t);
		for (int j = 0; j < 32; j++)
		{
			if (t & (1LL << j))
				b[i][j] = 1;
			b[i][j] += b[i - 1][j];
		}
	}
	ll ans = 0;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 0; j < 32; j++)
		{
			if (a[i][j] - a[i - 1][j] != b[i][j] - b[i - 1][j])
				ans = (ans + (1LL << j)) % mod;
			if (a[i][j] - a[i - 1][j] == 1)
				ans = (ans + (1LL << j) * (i - 1 - b[i - 1][j])) % mod;
			else
				ans = (ans + (1LL << j) * b[i - 1][j]) % mod;
			if (b[i][j] - b[i - 1][j] == 1)
				ans = (ans + (1LL << j) * (i - 1 - a[i - 1][j])) % mod;
			else
				ans = (ans + (1LL << j) * a[i - 1][j]) % mod;
		}
		pr("%lld%c", ans, i == n ? '\n' : ' ');
	}
}
C、阶乘
求一个最小的正整数 n,使得 n! 是 p 的倍数
考虑若 n 成立,那么所有>=n的数字的阶乘均成立,具有单调性,所以我们先枚举因子,然后二分出 n 即可,最后取一个最大值就是答案,主要 n 自己可能是个质数,所以最后和 n 取个最大值
#include <bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
using namespace std;
bool check(ll k, ll num, ll all)
{
	ll ans = 0;
	for (int i = num; i <= k * num; i = i * num)
	{
		ans += k * num / i;
		if (ans > 50)
			return true;
	}
	if (ans >= all)
		return true;
	return false;
}
ll get(ll n)
{
	ll ans = 1;
	for (ll i = 2; i * i <= n; i++)
	{
		if (n % i == 0)
		{
			ll cnt = 0;
			while (n % i == 0)
			{
				n /= i;
				cnt++;
			}
			ll l = 1, r = 1e9;
			while (l + 1 < r)
			{
				ll k = (l + r) / 2;
				if (check(k, i, cnt))
					r = k;
				else
					l = k;
			}
			if (!check(l, i, cnt))
				l = r;
			ans = max(ans, i * l);
		}
	}
	if (n > 1)
	{
		ans = max(ans, n);
	}
	return ans;
}
int main()
{
	int T;
	sc("%d", &T);
	while (T--)
	{
		ll n;
		sc("%lld", &n);
		pr("%lld\n", get(n));
	}
}
D、小石的签到题
考虑 1 可以单独取一手,也可以被其他任意一手取掉,如果第一个人先手不取 1 会输的话,那么他会先取1,反之,不取1,就是说第一个人稳赢,然后特判一下 n=1的情况
#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    scanf("%d", &n);
    if (n == 1)
        printf("Yang");
    else
        printf("Shi");
}
E、装备合成
有 n 个 a 和 m 个 b,2个a和3个b合成一件
装备,4个a和1个b合成一件装备,求最大合成的装备数量
首先假设合成了x个装备1和y个装备2
2x+3y<=n
3x+y<=m
z=x+y
然后会发现这玩意儿是个二次函数,先增再减,所以三分一下即可,由于精度存在问题,所以装备个数取double去比较,然后比较一下它左右两边的值即可
#include <bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
using namespace std;
double a, b;
double calc(ll numa)
{
    double aa = a, bb = b;
    aa -= numa * 2;
    bb -= numa * 3;
    double ans = numa + min(aa / 4, bb);
    return ans;
}
int main()
{
    int T;
    sc("%d", &T);
    while (T--)
    {
        sc("%lf%lf", &a, &b);
        ll l = 0, r = min(a / 2, b / 3);//numa
        while (l + 2 < r)
        {
            ll lmid = (r - l) / 3 + l;
            ll rmid = (r - l) / 3 * 2 + l;
            double lans = calc(lmid);
            double rans = calc(rmid);
            if (lans < rans)
                l = lmid;
            else
                r = rmid;
        }
        ll ans = 0;
        for (ll i = l; i <= r; i++)
            ans = max(ans, (ll)calc(i));
        pr("%lld\n", ans);
    }
}