2023年最后一哆嗦 题解
2023年最后一哆嗦
一边改题一边就给题解写了。
T1
这题看上去就像
这种求间隔的题,先给方程列出来,再考虑解。
设火车在走过
同理,设乔琨睡与醒过了
关于
那么方程是很好列出来的:
考虑变为
观察到
代码就很好写了。
//式子:2×(x+y)×m−(p+q)×a=(p+b)-(x+n)
#include <bits/stdc++.h>
#define int long long
using namespace std;
int exgcd(int &x, int &y, int a, int b) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int G = exgcd(x, y, b, a % b);
int t = x;
x = y;
y = t - a / b * y;
return G;
}
signed main() {
ios::sync_with_stdio(0);
int T;
cin >> T;
while (T--) {
int ans = 2e18;
int x, y, p, q;
cin >> x >> y >> p >> q;
int a = 2 * (x + y), b = p + q;
int X, Y;
int G = exgcd(X, Y, a, b);
// 枚举 b, n
bool glg = true;
for (int N = 0; N < y; N++) {
for (int B = 0; B < q; B++) {
int c = (p + B) - (x + N);
if (c % G != 0)
continue;
glg = false;
int XX = X * (c / G);//ax + by = c的一组解
XX = (XX % ((p + q) / G) + ((p + q) / G)) % ((p + q) / G);
ans = min(ans, a * XX + x + N);
}
}
if (glg)
puts("infinity");
else
cout << ans << "\n";
}
return 0;
}
T2
求
由
那么预先筛出质数,再枚举求出答案即可。
注意求答案时的细节问题。
#include <bits/stdc++.h>
#define int long long
#define N 10000007
using namespace std;
vector<int>v;
int phi[N];
bitset<N>pri;
int n;
void get_p() {
phi[1] = 1;
for (int i = 2; i <= n; i++) {
if(!pri[i]) {
v.push_back(i);
phi[i] = i - 1;
}
for(int j = 0; j < (int)v.size() && v[j] * i <= n; j++) {
pri[i * v[j]] = true;
if(i % v[j] == 0) {
phi[i * v[j]] = phi[i] * v[j];
break;
}
phi[i * v[j]] = phi[i] * phi[v[j]];
}
}
}
int sum[N];
int res;
signed main() {
scanf("%lld", &n);
get_p();
for (int i = 1; i <= n; i++)
sum[i] = sum[i - 1] + phi[i];
for(int j = 0; j < (int)v.size(); j++)
res += 2 * sum[n / v[j]] - 1;
cout << res << "\n";
return 0;
}
T3
大水题。
考虑可行情况=所有情况-不可行情况。
这里的所有情况就是
因此最终答案是
代码懒得放了。
T4
考虑一个显然正确的结论:
对于两个点
这个结论应当是显然的。如果不满足,必然还会有另一种移动方案使它不成为最优解。
那么对于权值最大的点
有了这个结论,就好做了。
贪心!!
贪心个辣子。对于一个点,你无法确定它给最左边放还是给最右边放。再何况,
根据上面的思路,相对较大的节点始终会在空位置的两端,因此相对小的节点始终会在空位置的中央并连成一个区间。
这不就是区间
那么状态只能由它的两边转移而来。
代码很好写。
记着开
#include <bits/stdc++.h>
#define N 2005
using namespace std;
long long dp[N][N];
struct Node {
int pos;
long long val;
} e[N];
bool operator < (const Node &a, const Node &b) {
return a.val < b.val;
}
int n;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
e[i].pos = i;
scanf("%lld", &e[i].val);
}
sort(e + 1, e + 1 + n);
for (int len = 1; len <= n; len++)
for (int i = 1; i + len - 1 <= n; i++) {
int j = i + len - 1;
dp[i][j] = max(dp[i + 1][j] + abs(e[j - i + 1].pos - i) * e[j - i + 1].val,
dp[i][j - 1] + abs(e[j - i + 1].pos - j) * e[j - i + 1].val);
}
cout << dp[1][n] << "\n";
return 0;
}
T5
小清新思维题
为了方便转化成题目所求的样子,我们先让每个
转化完之后的序列不好处理,考虑差分解。此时我们发现,目标情况就是差分序列全为
题目中说一个点只能作左/右端点各一次,因此当这个差分序列的两相邻元素的差值的绝对值大于1时,直接判断无解并输出。
那么差分序列的值只有三种情况:
为了方便统计答案,我们记当前可用左节点的数目为
- 当
时:
此时序列中的原值
- 当
时:
此时序列中的原值
- 当
时:
此时序列中的原值
没了。
代码是一如既往地好写:
#include <bits/stdc++.h>
#define N 2005
#define mod 1000000007
using namespace std;
int a[N];//原序列
int d[N];//差分序列
int n, h;
int main() {
scanf("%d%d", &n, &h);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
a[i] = h - a[i];
}
for (int i = 1; i <= n + 1; i++) {
d[i] = a[i] - a[i - 1];
if (abs(d[i]) > 1) {
puts("0");
return 0;
}
}
long long ans = 1, cnt = 0;
for (int i = 1; i <= n; i++)
if(d[i] == 1)
cnt++;
else if(d[i] == -1)
ans = ans * cnt % mod, cnt--;
else
ans = ans * (cnt + 1) % mod;
printf("%lld\n", ans);
return 0;
}
T6
这种涉及路径统计的东西,往往和
又看到
“车”走横竖,因此我们在
-
在终点
-
与终点同行不同列
-
与终点同列不同行
-
与终点不同列也不同行
上面的情况分别设为 个人习惯,行列不使用
初始化:
代码就很好写了。
#include <bits/stdc++.h>
#define int long long
#define N 1000005
#define mod 998244353
using namespace std;
int n, m, k;
int dp[N][4];
signed main() {
int x_1, x_2, y_1, y_2;
cin >> m >> n >> k >> x_1 >> y_1 >> x_2 >> y_2;
if(x_1 == x_2 && y_1 == y_2)
dp[0][0] = 1;
else if(x_1 == x_2 && y_1 != y_2)
dp[0][1] = 1;
else if(x_1 != x_2 && y_1 == y_2)
dp[0][2] = 1;
else
dp[0][3] = 1;
for (int i = 1; i <= k; i++) {
dp[i][0] = (dp[i - 1][1] % mod + dp[i - 1][2] % mod) % mod;
dp[i][1] = ((dp[i - 1][0] % mod * (n - 1) % mod + dp[i - 1][1] % mod * (n - 2) % mod) % mod + dp[i - 1][3] % mod) % mod;
dp[i][2] = ((dp[i - 1][0] % mod * (m - 1) % mod + dp[i - 1][2] % mod * (m - 2) % mod) % mod + dp[i - 1][3] % mod) % mod;
dp[i][3] = ((dp[i - 1][1] % mod * (m - 1) % mod + dp[i - 1][2] % mod * (n - 1) % mod) % mod + dp[i - 1][3] % mod * (m + n - 4) % mod) % mod;
}
cout << dp[k][0] << "\n";
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!