做题随笔2
gcd(n,n+1)=1
https://codeforces.com/problemset/problem/1521/B
s.find()
https://codeforces.com/problemset/problem/1845/C
做题反思:对于 \(s.find()\) 函数,前面为字符,后面为位置。
如果对一个字符串进行查找,查找完一个字符,要查找下一个字符串之前,需要对当前位置进行 \(+1\) 操作。

反悔贪心初识
https://codeforces.com/problemset/problem/1526/C2
思路:非负数药水全都喝掉,负数药水全都存到优先队列里,直到发现不够用了,检查是否能不喝亏损最大的药水来喝当前这瓶。
为什么不只存消耗最大的那一瓶呢?因为有可能前面喝了 \(-4,-5\) ,后面喝的两瓶都更优,所以要记所有的负数
按位贪心
https://codeforces.com/problemset/problem/484/A
思路:对于 \(l\) 来说,从低位开始贪心,若当前为 \(0\) ,设为 \(1\) ,看是否大于 \(r\),这样贪心可以使得 \(1\) 的数量变多的同时,使得当前数字尽量小
做题时的思路:从高位开始比较,从 \(l 和 r\) 第一个不同的位置开始,后面全是 \(1\)
哥德巴赫猜想
https://codeforces.com/problemset/problem/735/D
强猜想:对于任意一个大于2的偶数可以分为两个质数之和,
弱猜想:任意一个大于5的奇数可以分为三个质数之和
思路:利用结论,先处理质数,质数的代价一定为 \(1\),除2以外的偶数代价一定为 \(2\),再看大于 \(5\) 的奇数能不能分成一个 \(2\) 和一个质数,如果可以,代价为 \(2\),反之为 \(3\)。
trick
https://codeforces.com/problemset/problem/1514/C
注意:几个数的乘积与 \(x\) 互质,当且仅当这几个数中的每一个数都与 \(x\)互质,并且乘积对 \(x\) 取模的余数也和 \(x\) 互质
思路:挑出序列中所有与 \(n\) 互质的数,模 \(n\) 后的结果 \(res\) 一定是和 \(n\) 互质的,因为 \(res\) 是模 \(n\) 得到的,所以一定小于 \(n\) ,如果这个数为 \(1\) ,那么答案就找到了,如果不为 \(1\),那么只要在序列中去除这个数就可以了
gcd(a,b)=gcd(a-b,b)
https://codeforces.com/problemset/problem/1458/A
这个性质不只是对两个数成立,多个数的时候也是成立的,所以原题中的 \(gcd(a_1+b_j,\cdots,a_n+b_j)\),就可以变成 \(gcd(a_1+b_j,\cdots,a_n-a_1)\),也就是后面的数全都减去第一个数,这样就可以预处理后面 \(n-1\) 个元素,遍历得到第一个元素就可以了
Code
点击查看代码
void solve()
{
cin >> n >> m;
vi a(n + 1), b(m + 1);
int res = 0;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
if (i != 1)
res = gcd(res, abs(a[i] - a[1]));
}
for (int i = 1; i <= m; i++)
{
cin >> b[i];
cout << gcd(a[1] + b[i], res) << ' ';
}
}
反向图
思路:看似是双向奔赴,找出一个中间点,\(dist(1,i)=dist(1,k)+dist(k,i)\) ,如果直接进行计算,要对每一个点跑最短路,时间复杂度太大,所以建反图,代表另一只手的操作,这样的操作,就像是一个点从起点开始走,走到一定的地方可以把所有边方向全部反过来(只允许反一次)。所以对 点 \(i\) 和点 \(i+n\) 之间连一条边权为 \(0\) 的边,具体操作看代码
Code
点击查看代码
struct node
{
int to, w;
};
vector<node> adj[M];
void solve()
{
cin >> n >> m;
while (m--)
{
int u, v, w;
cin >> u >> v >> w;
adj[u].push_back({v, w});
adj[v + n].push_back({u + n, w});
}
for (int i = 1; i <= n; i++)
{
adj[i].pb({i + n, 0});
}
priority_queue<pii, vector<pii>, greater<pii>> p;
vi res(2 * n + 7, -1);
p.push({0, 1});
res[1] = 0;
while (p.size())
{
auto [d, i] = p.top();
p.pop();
if (d > res[i])
continue;
for (auto [j, w] : adj[i])
{
if (res[j] == -1 || res[j] > w + res[i])
{
res[j] = w + res[i];
p.push({res[j], j});
}
}
}
for (int i = 2; i <= n; i++)
{
cout << res[i + n] << ' ';
}
}

浙公网安备 33010602011771号