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