2023杭电第六场补题报告1001 1002 1003 1006 1010
1001 Count (hdu.edu.cn)
思路
直接推公式n-k为一个循环节。
代码
#include <bits/stdc++.h>
#define int long long
#define LL long long
#define endl '\n'
//#define P pair<int,int>
#define FOR(i,n) for(int i = 1;i <= n;i ++)
#define FOP(i,n) for(int i = 0;i < n;i ++)
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 2e5 + 5;
const int mod = 998244353;
int n,m,k,x,y,a[N],pre[N];
int qpow(int a,int b)
{
a %= mod;
int ans=1;
while(b){
if(b&1)
ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
void solve(){
cin >> n >> m >> k;
if(n != k){
cout << qpow(m, n - k) << "\n";
}
else{
cout << qpow(m, n) << "\n";
}
}
signed main() {
ios_base::sync_with_stdio(0),cin.tie(0);
//freopen("in.txt", "r", stdin);
int t = 1;
cin >> t;
while(t--) solve();
return 0;
}
1002 Pair Sum and Perfect Square (hdu.edu.cn)
思路
直接使用树状数组,然后线性的扫一遍算每个数会在哪个区间内造成贡献。
代码
#include <iostream>
#include <array>
#include <vector>
#include <algorithm>
#include <functional>
#include <cstring>
using namespace std;
const int N = 200010;
int p[N], pos[N];
int sq[N], m, n, k;
struct Fenwick {
int tr[N];
inline int lowbit(int x) {
return x & -x;
}
inline void add(int x, int v) {
for (; x <= n; x += lowbit(x))
tr[x] += v;
}
inline int ask(int x) {
int res = 0;
for (; x; x -= lowbit(x))
res += tr[x];
return res;
}
void clear() {
memset(tr, 0, sizeof tr);
}
} t;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int T;
cin >> T;
while (T--) {
t.clear();
cin >> n;
m = 0;
for (int i = 1; i * i <= 2 * n - 1; i++) {
sq[++m] = i * i;
}
for (int i = 1; i <= n; i++) {
cin >> p[i];
pos[p[i]] = i;
}
cin >> k;
vector<vector<pair<int, int>>> q(n + 1);
for (int i = 1; i <= k; i++) {
int l, r;
cin >> l >> r;
q[r].emplace_back(i, l);
}
int tot = 0;
vector<int> ans(k + 1);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (sq[j] <= p[i]) continue;
if (sq[j] - p[i] > n) break;
if (pos[sq[j] - p[i]] < i) t.add(pos[sq[j] - p[i]], 1), ++tot;
}
for (auto [id, l] : q[i]) {
ans[id] = tot - t.ask(l - 1);
}
}
for (int i = 1; i <= k; i++) {
cout << ans[i] << '\n';
}
}
return 0;
}
1003 Vector (hdu.edu.cn)
思路
高斯消元接方程组,就是精度要求很高,eps需要至少开到 1 0 − 9 10^{-9} 10−9
代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc second
#define double long double
using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 110;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
const int maxn = 10;
const double eps = 1e-14;
double a[maxn][maxn];
int equ, var; // equ个方程,var个变量
double x[maxn]; //解集
bool free_x[maxn];
int n;
int sgn(double x) { return (x > eps) - (x < -eps); }
// 高斯消元法解方程组(Gauss-Jordan
// elimination).(0表示无解,1表示唯一解,大于1表示无穷解,并返回自由变元的个数)
int gauss() {
equ = n, var = n; //多少个方程,多少个变量
int i, j, k;
int max_r; // 当前这列绝对值最大的行.
int col; // 当前处理的列.
double temp;
int free_x_num;
int free_index;
// 转换为阶梯阵.
col = 0; // 当前处理的列.
memset(free_x, true, sizeof(free_x));
for (k = 0; k < equ && col < var; k++, col++) {
max_r = k;
for (i = k + 1; i < equ; i++) {
if (sgn(fabs(a[i][col]) - fabs(a[max_r][col])) > 0) max_r = i;
}
if (max_r != k) { // 与第k行交换.
for (j = k; j < var + 1; j++) swap(a[k][j], a[max_r][j]);
}
if (sgn(a[k][col]) ==
0) { // 说明该col列第k行以下全是0了,则处理当前行的下一列.
k--;
continue;
}
for (i = k + 1; i < equ; i++) { // 枚举要删去的行.
if (sgn(a[i][col]) != 0) {
temp = a[i][col] / a[k][col];
for (j = col; j < var + 1; j++) {
a[i][j] = a[i][j] - a[k][j] * temp;
}
}
}
}
for (i = k; i < equ; i++) {
if (sgn(a[i][col]) != 0) return -1;
}
if (k < var) {
return var - k;
}
for (i = var - 1; i >= 0; i--) {
temp = a[i][var];
for (j = i + 1; j < var; j++) {
if (sgn(a[i][j]) != 0) temp -= a[i][j] * x[j];
}
x[i] = temp / a[i][i];
if (sgn(x[i]) < 0) return -1;
}
return 0;
}
void solve() {
n = 3;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> a[j][i];
}
}
for (int i = 0; i < 3; i++) cin >> a[i][3];
int ok = gauss();
if (ok == 0) {
cout << "YES\n";
return;
} else if (ok == -1) {
cout << "NO\n";
return;
} else {
int tmp[5][5];
for (int i = 0; i < 3 - ok; i++) {
for (int j = 0; j < 4; j++) {
tmp[i][j] = a[i][j];
}
}
if (ok == 2) {
for (int i = 0; i < 3; i++) {
if (sgn(a[0][i]) != 0) {
if (sgn(a[0][3]) * sgn(a[0][i]) >= 0) {
cout << "YES\n";
return;
}
} else {
if (sgn(a[0][3]) == 0) {
cout << "YES\n";
return;
}
}
}
} else {
a[0][0] = tmp[0][1], a[0][1] = tmp[0][2], a[0][2] = tmp[0][3];
a[1][0] = tmp[1][1], a[1][1] = tmp[1][2], a[1][2] = tmp[1][3];
n = 2;
if (gauss() == 0) {
cout << "YES\n";
return;
}
a[0][0] = tmp[0][0], a[0][1] = tmp[0][2], a[0][2] = tmp[0][3];
a[1][0] = tmp[1][0], a[1][1] = tmp[1][2], a[1][2] = tmp[1][3];
if (gauss() == 0) {
cout << "YES\n";
return;
}
a[0][0] = tmp[0][0], a[0][1] = tmp[0][1], a[0][2] = tmp[0][3];
a[1][0] = tmp[1][0], a[1][1] = tmp[1][1], a[1][2] = tmp[1][3];
if (gauss() == 0) {
cout << "YES\n";
return;
}
cout << "NO\n";
}
}
}
signed main() {
IOS;
int t = 1;
cin >> t;
for (int i = 1; i <= t; i++) {
solve();
}
}
1006 Perfect square number (hdu.edu.cn)
思路
观察到数据范围其实只有300左右,所以我们完全可以直接进行 n 3 n^3 n3的暴力枚举,但是需要进行一个线性的维护,进入到下一个位置时只丢弃包含上一个位置但不包含下一个位置的,加入包含下一位置不包含上一位置的。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve();
void init();
signed main(){
cin.sync_with_stdio(0);
cin.tie(0);
init();
int T = 1;
cin >> T;
while(T--){
solve();
}
return 0;
}
#define N 330
int pq[N * N * 10];
void init(){
for(int i = 1;i * i < N * N;i++){
pq[i * i] = 1;
}
}
int tot[2 * N];
int a[N];
void solve(){
int n;
cin >> n;
memset(tot, 0, sizeof tot);
for(int i = 1;i <= n;i++){
cin >> a[i];
}
int oans = 0;
for(int i = 1;i <= n;i++){
int sum = 0;
for(int j = i;j <= n;j++){
sum += a[j];
if(pq[sum] == 1)oans++;
}
}
//cout << oans << "\n";
int ans = oans;
for(int i = 1;i <= n;i++){
//删除
int sum = 0;
for(int j = i - 1;j >= 1;j--){
sum += a[j];
for(int k = -300;k <= 300;k++){
if(sum + k >= 0)
if(pq[sum + k] == 1)tot[k + N]--;
}
}
//增加
sum = 0;
for(int j = i;j <= n;j++){
sum += a[j];
for(int k = -300;k <= 300;k++){
if(sum + k >= 0)
if(pq[sum + k] == 1)tot[k + N]++;
}
}
//统计
int mx = 0;
for(int j = 1;j <= 300;j++){
mx = max(mx, tot[j - a[i] + N]);
}
ans = max(ans, oans - tot[N] + mx);
}
cout << ans << "\n";
}
1010 Calculate (hdu.edu.cn)
思路
先想的暴力预处理 n 2 {n^2} n2存储,但是发现数据范围存不下,所以想到倍增存储 32 ∗ n 32*n 32∗n
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve();
signed main(){
cin.sync_with_stdio(0);
cin.tie(0);
int T = 1;
cin >> T;
while(T--){
solve();
}
return 0;
}
#define mod 1000000007
#define N 100100
int to[N][32];
int k[N][32];
int b[N][32];
int k1[N];
int b1[N];
void solve(){
int n, q;
cin >> n >> q;
for(int i = 1;i <= n;i++){
cin >> k1[i];
}
for(int i = 1;i <= n;i++){
cin >> b1[i];
}
for(int i = 1;i <= n;i++){
int p;
cin >> p;
to[i][0] = p;
k[i][0] = k1[p];
b[i][0] = b1[p];
}
for(int j = 1;j < 31;j++){
for(int i = 1;i <= n;i++){
to[i][j] = to[to[i][j - 1]][j - 1];
k[i][j] = k[i][j - 1] * k[to[i][j - 1]][j - 1] % mod;
b[i][j] = b[i][j - 1] * k[to[i][j - 1]][j - 1] % mod + b[to[i][j - 1]][j - 1];
b[i][j] %= mod;
}
}
while(q--){
int x, l, y;
cin >> x >> l >> y;
int kk = 1, bb = 0;
for(int i = 30;i >= 0;i--){
if(l >= (1 << i)){
bb = bb * k[x][i] % mod + b[x][i];
bb %= mod;
kk = kk * k[x][i];
kk %= mod;
x = to[x][i];
l -= (1 << i);
}
}
//cout << kk << "\n";
cout << (y * kk % mod + bb) % mod << "\n";
}
}