2022 纪中集训 7.16 笔记
T1 GMOJ 6277. 矩阵游戏
观察表格中的 \((i, j)\) 点可以表示为 \((i-1) \times m + j\)。
由于列和行是相似的,这里只讨论行修改。
考虑推式子。
对于每一次行操作:
\[ans_r = \sum_{j=0}^{m} r_i \times [(i-1)\times + j]
\]
\[= \sum_{j=0}^{m} [r_i \times (i-1) \times m + r_i \times j]
\]
\[= \sum_{j=0}^{m} r_i \times (i-1) \times m + \sum_{j=0}^{m} r_i \times j
\]
发现前半部分可以预处理, 后半部分可以将所有的 \(r_i\) 先加起来再算贡献。
点击查看代码
#include <bits/stdc++.h>
typedef long long LL;
using namespace std;
const LL N = 1000005;
const LL Mod = 1e9 + 7;
inline LL read()
{
register LL x = 0, f = 1;
register char ch = getchar();
while(ch < '0' || ch > '9')
{
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
return x * f;
}
LL s[N],r[N];
int main()
{
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
LL n = read(), m = read(), q = read();
for (LL i=1;i<=n;++i) r[i] = 1;
for (LL i=1;i<=m;++i) s[i] = 1;
for (LL i=1;i<=q;++i)
{
char opt[2];
scanf("%s",opt);
LL x = read(), y = read();
if (opt[0] == 'R') r[x] = (r[x]*y)%Mod;
if (opt[0] == 'S') s[x] = (s[x]*y)%Mod;
}
LL sum1 = 0;
for (LL i=1;i<=n;++i) sum1 = ((((r[i] * m) % Mod * (i-1)) % Mod) + sum1) % Mod;
LL sum2 = 0;
for (LL i=1;i<=n;++i) sum2 = (sum2 + r[i]) %Mod;
LL ans = 0;
for (LL j=1;j<=m;++j) ans = (ans + (sum1 + sum2 * j % Mod) % Mod * s[j] % Mod) % Mod;
printf("%lld\n",ans);
return 0;
}
T2 GMOJ 1385. 直角三角形
选择一个点 \(P\),并且平移平面直角坐标系使得 \(P\) 点与原点重合。
现在,对于每个点,先确定它在哪个象限里面。
然后将它顺时针旋转 \(90^{\circ}\),直至它位于第一象限。
在那之后,按照斜率将每个点排序
与 \(P\) 点能形成直角三角形的两个点,一定有着相同的斜率.
并且旋转前位于相邻的两个象限内。
排序之后,对于有着同样斜率的一组点,
统计四个象限内分别有多少个点,
并把相邻的象限的点的个数相乘即可得到答案.
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1505;
int n;
LL ans;
int cnt[5];
struct Node
{
LL x, y;
int quadrant;
bool operator< (const Node& t) const
{
return y * t.x < x * t.y;
}
} a[N], b[N];
void rotate(int p)
{
if (a[p].x == 0 && a[p].y == 0) return;
a[p].quadrant = 1;
while (a[p].x <= 0 || a[p].y < 0)
{
swap(a[p].x, a[p].y);
a[p].y = -a[p].y;
a[p].quadrant++;
}
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%lld%lld", &b[i].x, &b[i].y);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
a[j].x = b[j].x - b[i].x;
a[j].y = b[j].y - b[i].y;
rotate(j);
}
swap(a[1], a[i]);
sort(a + 2, a + n + 1);
int j = 2;
while (j <= n)
{
int k = j;
memset(cnt, 0, sizeof cnt);
while (k <= n && a[j].y * a[k].x == a[j].x * a[k].y)
{
cnt[a[k].quadrant]++;
k++;
}
for (int t = 1; t <= 4; t++) ans += cnt[t] * cnt[t%4 + 1];
j = k;
}
}
printf("%lld", ans);
return 0;
}