【2021夏纪中游记】2021.7.15模拟赛

2021.7.15模拟赛

比赛概括:

(mathrm{sum}=40+0+30+0)

本来可以拿 (200),但是因为没审完题。唉。

T1 彩色圆环:

原题,详见 【YBTOJ】【国家集训队】彩色圆环

T2 折射伤害:

题目大意:

在一个游戏中有n个英雄,初始时每个英雄受到数值为ai的伤害,每个英雄都有一个技能“折射”,即减少自己受到的伤害,并将这部分伤害分摊给其他人。对于每个折射关系,我们用数对(xi,yi,zi)来表示xi将自己受到伤害去掉zi的比例,将这些伤害转移给yi(xi,yi是整数,zi是实数)。

求出经过反复折射后最后每个英雄受到的实际总伤害。

思路:

求出第 (i) 个英雄收到的总伤害(包括折射收到的)(f(i)),可以发现:

[f(i)=a_i+sum_{j e i}z_{j,i}f(j) ]

以此得到增广矩阵:

[left[egin{array}{lcccr|r} 1&-z_{2,1}&-z_{3,1}&cdots&-z_{n,1}&a_1\ -z_{1,2}&1&-z_{3,2}&cdots&-z_{n,2}&a_2\ -z_{1,3}&-z_{2,3}&1&cdots&-z_{n,3}&a_3\ vdots&vdots&cdots&ddots&vdots&vdots\ end{array} ight]]

高斯消元求解后,再乘上反弹出去的比例就行了。

代码:

const int N = 210;

inline ll Read()
{
	ll x = 0, f = 1;
	char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = -f, c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
	return x * f;
}

int n, m;
double a[N][N], ref[N];

void Gauss()
{
	for (int i = 1; i <= n; i++)
	{
		int mxi = i;
		for (int j = i + 1; j <= n; j++)
			if(fabs(a[mxi][i]) < fabs(a[j][i])) mxi = j;
		swap(a[mxi], a[i]);
		double inv = a[i][i];
		for (int j = i; j <= n + 1; j++)
			a[i][j] /= inv;
		for (int j = i + 1; j <= n; j++)
		{
			double inv = a[j][i];
			for (int k = i + 1; k <= n + 1; k++)
				a[j][k] -= inv * a[i][k];
		}
	}
	for (int i = n - 1; i; i--)
		for (int j = i + 1; j <= n; j++)
			a[i][n + 1] -= a[i][j] * a[j][n + 1];
}

int main()
{
	n = Read();
	for (int i = 1; i <= n; i++)
		a[i][i] = 1.0, a[i][n + 1] = Read() * 1.0;
	m = Read();
	for (int i = 1; i <= m; i++)
	{
		int x = Read(), y = Read(); double z;
		scanf("%lf", &z);
		a[y][x] -= z, ref[x] += z;
	}
	Gauss();
	for (int i = 1; i <= n; i++)
		printf ("%.6f
", a[i][n + 1] * (1 - ref[i]));
	return 0;
}

T3 鱼跃龙门:

题目大意:

给定 (n),找到最小的 (x) 使得 (2n|x(x+1))

正文:

我们知道 (2n=p_1^{c_1} imes p_2^{c_2} imescdots imes p_m^{c_m})

找到其中最大的幂 (p_x^{c_x})。在 ([1,2n]) 内枚举它的倍数然后在相邻数中检测是否 (2n) 的其它幂都能被包含。时间复杂度 (mathcal{O}(Tsqrt{n}mathrm{cnt})),其中 (mathrm{cnt}) 表示 (2n) 的质因数个数,理论上说会被卡,但又好像和标算差不多。

代码:

const int N = 1e6 + 10;

inline ll Read()
{
	ll x = 0, f = 1;
	char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = -f, c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
	return x * f;
}

bool vis[N];
ll pri[N], cnt;
void Prime()
{
	for (int i = 2; i <= N - 10; i++)
	{
		if (!vis[i]) pri[++cnt] = i, vis[i] = 1;
		for (int j = 1; j <= cnt && pri[j] * i <= N - 10; j++)
		{
			vis[pri[j] * i] = 1;
			if (!(i % pri[j])) break;
		}
	}
}

int t;
ll n;
ll a[N][2], tot;

ll qpow(ll a, ll b)
{
	ll ans = 1;
	for (; b; a = a * a, b >>= 1)
		if (b & 1) ans = ans * a;
	return ans;
}

int main()
{
	Prime();
	for (t = Read(); t--; )
	{
		n = Read(); n *= 2;
		ll m = n;
		a[tot = 1][0] = 1, a[tot][1] = 1;
		for (int i = 1; i <= cnt; i++)
		{
			if (m % pri[i]) continue;
			a[++tot][0] = pri[i];
			a[tot][1] = 0;
			for (; !(m % pri[i]); m /= pri[i])
				a[tot][1]++;
			if (m == 1) break;
		}
		if (m != 1) a[++tot][0] = m, a[tot][1] = 1;
		for (ll i = 1, val = qpow(a[tot][0], a[tot][1]); i * val <= n; i++)
		{
			int flag = 1;
			for (int j = 1; j < tot; j++)
			{
				ll val1 = qpow(a[j][0], a[j][1]);
				if ((i * val - 1) % val1 && (i * val) % val1) {flag = 0; break;}
			}
			if (flag) {printf ("%lld
", i * val - 1); break;};
			flag = 1;
			for (int j = 1; j < tot; j++)
			{
				ll val1 = qpow(a[j][0], a[j][1]);
				if ((i * val + 1) % val1 && (i * val) % val1) {flag = 0; break;}
			}
			if (flag) {printf ("%lld
", i * val); break;};
		}
	}
	return 0;
}

T4 [GDOI2017]凡喵识图:

题目大意:

正文:

傻逼文字游戏题目描述。哈希搞搞就好了,个人感觉本题考验代码实现能力。

代码:

const int N = 150010;

inline ll Read()
{
	ll x = 0, f = 1;
	char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = -f, c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
	return x * f;
}

int n;
ll a[N];
int b[5], vis[N];
int nxt[5][N];

map<int, int> hash[5];

int Solve(ll x)
{
	int i = 0;
	for (; x; x -= x & -x, i++)
		if (i > 3) return 4;
	return i;
}

int main()
{
	freopen("hashing.in", "r", stdin);
	freopen("hashing.out", "w", stdout);
	n = Read();
	for (int i = 1; i <= n; i++)
	{
		a[i] = Read();
		for (int j = 0; j < 4; j++)
			b[j] = (a[i] >> j * 16) % (1 << 16);
		int ans = 0;
		for (int j = 0; j < 4; j++)
		{
			if (hash[j].find(b[j]) != hash[j].end())
			{
				nxt[j][i] = hash[j][b[j]];
				for (int k = nxt[j][i]; k; k = nxt[j][k])
				{
					if (vis[k] == i) continue; vis[k] = i;
					if (Solve (a[i] ^ a[k]) == 3) ans++;
				}
			} 
			hash[j][b[j]] = i;
		}
		printf ("%d
", ans);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/GJY-JURUO/p/15017826.html