2023杭电多校第六场 - 1 6 10
比赛地址:传送门
赛时过了 3 题,今天罚时多,而且出题慢
1001 思维签到题
1006 数学题
1010 倍增问题
1001 Count
题意
让你构造一个长为 n 的数组满足每个数均 $\in [1, m] $,且对于 $i \le k $,有 $A_i = A_{n - k + i} $。问你所有满足条件的数组的个数取模 998244353
思路
条件 2 将整个数组的前一半和后一半联系了起来,即 k 就是数组前后缀相等的个数。那么我们只需要确定剩下的不确定的位置就行了。
- 当 $n = k $ 时,条件 2 相当于没有,所以答案即为 $m ^ n $
- 当 $n \ne k $ 时,我们只需要确定剩下 \(n - k\)个位置即可,所以答案为 $ m ^ {n - k} $
代码
const int maxm = 2e5 + 5, inf = 0x3f3f3f3f, mod = 998244353;
ll qpow(ll a, ll x){
a %= mod;
ll res = 1;
while(x){
if(x & 1) res = res * a % mod;
x >>= 1;
a = a * a % mod;
}
return res;
}
void solve(){
ll n, m, k;
cin >> n >> m >> k;
if(n == k) cout << qpow(m, n) << '\n';
else cout << qpow(m, n - k) << '\n';
return ;
}
1006 Perfect square number
题意
给你长为 n 的数组,每个数的大小均在 $[1, 300] $ 之间。你尽可以操作一次,可以选择数组中任意的一个数,将其变为 $[1, 300] $ 之间的一个数。问你最大的区间个数满足这些区间和均为完全平方数。
思路
我们如果考虑每一个数在 $[1, 300] $ 里面选择,遍历每一个区间取最大值,那么 $O(n^4) $ 必定是 TLE 的。接下来我们考虑优化:
- 对于每一个数来说,其修改后仅对包含其的区间产生影响;
- 改变一个数 y 仅能影响区间和的范围是 \([sum - y + 1, sum - y + 300]\),而这个区间内的完全平方数的个数是远远小于 300 个的;
基于以上两点,我们可以先预处理出所有的完全平方数,再对每一个数 y 进行考虑:对于不包含该数的区间,满足题意的存下个数;对于包含该数的区间,求其当 y = 1 时的区间和,再在求得的完全平方数的序列中找到第一个大于等于其的位置,统计 \(y = [1, 300]\) 范围内哪些 y 可以使得当前区间和变为完全平方数,利用一个数组统计。那么,我们就得到了不包含当前数的合法区间数和包含当前数的合法 y 值。
最后我们循环遍历所有数,遍历其所有可能,取不包含 + 包含最大值的最大值即为最终答案
最终跑了 811 MS 应当是还存在更快的方法,日后再说
代码
//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x, y, sizeof(x))
#define debug(x) cout << #x << " = " << x << '\n'
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << '\n'
//#define int long long
using namespace std;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef pair<double, double> pdd;
/*
*/
const int maxm = 1e3 + 5, inf = 0x3f3f3f3f, mod = 998244353;
bool v[maxm * maxm];
vector<int> f;
void pre(){
f.push_back(0);
for(int i = 1; i <= 300; ++ i){
v[i * i] = true;
f.push_back(i * i);
}
return ;
}
void solve(){
int n;
cin >> n;
vector<int> a(n + 1), sum(n + 1), c(n + 1);
vector<vector<int>> cnt(n + 1, vector<int>(310, 0));
for(int i = 1; i <= n; ++ i){
cin >> a[i];
sum[i] = sum[i - 1] + a[i];
}
int len = f.size();
for(int k = 1; k <= n; ++ k){
for(int i = 1; i <= n; ++ i){
for(int j = i; j <= n; ++ j){
if(j < k || i > k){
if(v[sum[j] - sum[i - 1]]){
++ c[k];
}
continue;
}
int t = sum[j] - sum[i - 1] + 1 - a[k];
auto it = lower_bound(f.begin(), f.end(), t) - f.begin();
for(int l = it; l < len; ++ l){
if(f[l] - t + 1> 300) break;
++ cnt[k][f[l] - t + 1];
}
}
}
}
int ans = 0;
for(int i = 1; i <= n; ++ i){
int temp = 0;
for(int j = 1; j <= 300; ++ j){
temp = max(temp, cnt[i][j]);
}
ans = max(ans, temp + c[i]);
}
cout << ans << '\n';
return ;
}
signed main(){
pre();
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
cin >> _;
while(_ --){
solve();
}
return 0;
}
1010 Calculate
题意
详见题目
有一个 n 个节点的图,每个顶点一定有唯一一条出边。如果说 Ming 当前手上拥有的数字为 \(y\),当他走到节点 i 时,手上的数字变为 $y \times k_i + b_i $。
给你 q 次询问,每次 Ming 从节点 x 出发走 l 步,初始手上数字为 y ,问你最终数字取模 1e9 + 7
思路
利用倍增维护即可,详见代码
代码
//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x, y, sizeof(x))
#define debug(x) cout << #x << " = " << x << '\n'
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << '\n'
//#define int long long
using namespace std;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef pair<double, double> pdd;
/*
*/
const int maxm = 1e5 + 5, inf = 0x3f3f3f3f, mod = 1e9 + 7, N = 30;
int n, q, p[maxm], k[maxm], b[maxm];
ll fk[maxm][N + 1], fb[maxm][N + 1], f[maxm][N + 1];
bool vis[maxm];
void solve(){
mem(vis, false);
mem(fk, 0); mem(fb, 0); mem(f, 0);
cin >> n >> q;
for(int i = 1; i <= n; ++ i) cin >> k[i];
for(int i = 1; i <= n; ++ i) cin >> b[i];
for(int i = 1; i <= n; ++ i){
cin >> p[i];
f[i][0] = p[i];
fk[i][0] = k[p[i]];
fb[i][0] = b[p[i]];
}
for(int i = 1; i <= n; ++ i){
f[i][0] = p[i];
fk[i][0] = k[p[i]] % mod;
fb[i][0] = b[p[i]] % mod;
}
for(int i = 0; i < N; ++ i){
for(int j = 1; j <= n; ++ j){
f[j][i + 1] = f[f[j][i]][i];
fk[j][i + 1] = fk[j][i] * fk[f[j][i]][i] % mod;
fb[j][i + 1] = (fb[j][i] * fk[f[j][i]][i] % mod + fb[f[j][i]][i]) % mod;
}
}
while(q--){
ll x, y, l, ans;
cin >> x >> l >> y;
ans = y;
for(int i = N; i >= 0; -- i){
if(l >= (1ll << i)){
l -= 1ll << i;
ans = (ans * fk[x][i] % mod + fb[x][i]) % mod;
x = f[x][i];
}
}
cout << ans << '\n';
}
return ;
}
signed main(){
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
cin >> _;
while(_ --){
solve();
}
return 0;
}
本文来自博客园,作者:Qiansui,转载请注明原文链接:https://www.cnblogs.com/Qiansui/p/17604134.html