ABC-288解题报告
D. Range Add Query
题意:有一个序列
和正整数 ,每次询问给定 ,你可以在 内选择一段长度为 的子段,统一加减,问是否能将 全部变为 。
考虑操作在差分数组上的体现:选两个距离为
By jiangly
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, k;
std::cin >> n >> k;
std::vector<int> a(n);
std::vector<i64> s(n);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
s[i] = a[i];
if (i >= k) {
s[i] += s[i - k];
}
}
int q;
std::cin >> q;
while (q--) {
int l, r;
std::cin >> l >> r;
l--, r--;
std::vector<i64> b(k);
for (int i = r; r - i + 1 <= k; i--) {
b[i % k] += s[i];
}
for (int i = l - 1; i >= 0 && l - i <= k; i--) {
b[i % k] -= s[i];
}
if (b == std::vector(k, b[0])) {
std::cout << "Yes\n";
} else {
std::cout << "No\n";
}
}
return 0;
}
E. Wish List
题意:一个商店有
个商品,你需要买其中的 个(告诉你是哪 个)。每个商品有本身的价格 ,如果你买的商品在剩余商品中排第 位,则需额外付 元。如果需要,你也可以买 个之外的物品。问最小价格。
容易发现,后面如何选对前面没有影响,但前面如何选对后面有影响。如果不知道前面的状态,后面的完全无法确定。所以考虑从前往后 DP。
设
如果不买,则为
By apaid
const int N=5010;
int n,m,a[N],c[N],mark[N],mn[N][N];
ll dp[N][N];
int main() {
scanf("%d%d",&n,&m);
rep(i,0,n) scanf("%d",&a[i]);
rep(i,0,n) scanf("%d",&c[i]);
rep(i,0,n) {
mn[i][i]=c[i];
rep(j,i+1,n) mn[i][j]=min(mn[i][j-1],c[j]);
}
rep(i,0,m) {
int x;
scanf("%d",&x);
--x;
mark[x]=1;
}
memset(dp,0x20,sizeof(dp));
dp[0][0]=0;
rep(i,0,n) rep(j,0,i+1) {
dp[i+1][j]=min(dp[i+1][j],dp[i][j]+a[i]+mn[j][i]);
if (!mark[i]) dp[i+1][j+1]=min(dp[i+1][j+1],dp[i][j]);
}
ll ans=1ll<<60;
rep(j,0,n+1) ans=min(ans,dp[n][j]);
printf("%lld\n",ans);
}
F. Integer Division
题意:有一个长度为
的数字串,将其划分成若干段,一种划分方案的权值为每段表示的数的乘积。求所有划分方案的权值和,对 取模。
设
分别维护
By cxm1024
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 998244353;
int ksm(int a, int b, int res = 1) {
for(; b; a = a * a % mod, b >>= 1)
if(b & 1) res = res * a % mod;
return res;
}
int inv(int x) {return ksm(x, mod - 2);}
int f[200010], s[200010], t[200010], sumf[200010], sumfs[200010];
signed main() {
int n;
string x;
cin >> n >> x;
int now = 1;
for(int i = n - 1; i >= 0; i--, now = now * 10 % mod)
t[i + 1] = (x[i] - '0') * now % mod;
for(int i = 1; i <= n; i++)
s[i] = (s[i - 1] + t[i]) % mod;
f[0] = 1, sumf[0] = 1, sumfs[0] = 0;
for(int i = 1; i <= n; i++) {
f[i] = (sumf[i - 1] * s[i] % mod - sumfs[i - 1] + mod) % mod;
(f[i] *= inv(ksm(10, n - i))) %= mod;
sumf[i] = (sumf[i - 1] + f[i]) % mod;
sumfs[i] = (sumfs[i - 1] + f[i] * s[i] % mod) % mod;
}
cout << f[n] << endl;
return 0;
}
G. 3^N Minesweeper
题意:有一个
的 数组 ,生成一个数组 ,其中 表示与 相邻的 的 之和。两个数相邻的定义为,三进制下每个对应位的距离都不超过 。已知 ,求 。
对于
要想知道每个格子是否有雷,可以进行“降维打击”。具体地:
容易发现,右边的三个量恰好等于中间那列在一维问题上的
即可得出左边列作为一维问题的
在实现上,选择两个“边”和一个“中间”来进行容斥,它们只有一位的差距,中间块该位为
递归 By cxm1024
#include <bits/stdc++.h>
using namespace std;
int n, e[13], f[600000];
void solve(int now, int nowx) {
if(now == n + 1) return;
int tmp = e[now];
now++;
for(int i = 0; i < e[n - now]; i++)
f[nowx + tmp + i * e[now]] = f[nowx + i * e[now]] + f[nowx + tmp * 2 + i * e[now]] - f[nowx + tmp + i * e[now]];
for(int i = 0; i < e[n - now]; i++) {
f[nowx + i * e[now]] -= f[nowx + tmp + i * e[now]];
f[nowx + 2 * tmp + i * e[now]] -= f[nowx + tmp + i * e[now]];
}
solve(now, nowx + tmp);
solve(now, nowx), solve(now, nowx + 2 * tmp);
}
signed main() {
e[0] = 1;
for(int i = 1; i <= 12; i++)
e[i] = e[i - 1] * 3;
cin >> n;
for(int i = 0; i < e[n]; i++)
cin >> f[i];
solve(0, 0);
for(int i = 0; i < e[n]; i++)
cout << f[i] << " ";
cout << endl;
return 0;
}
循环 By miao22
#include<bits/stdc++.h>
using namespace std;
int n,a[1000003],m;
int main(){
ios::sync_with_stdio(0);
cin.tie(NULL);
cout.tie(NULL);
cin>>n;
m=pow(3,n);
for(int i=0;i<m;i++)
cin>>a[i];
int pw=1;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++)
if(j%(pw*3)<pw){
int x=a[j],y=a[j+pw],z=a[j+pw+pw];
a[j]=y-z;
a[j+pw]=x+z-y;
a[j+pw+pw]=y-x;
}
pw*=3;
}for(int i=0;i<m;i++)
cout<<a[i]<<' ';
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步