2023杭电第六场补题报告1001 1002 1003 1006 1010

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} 109

代码

#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 32n

代码

#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";
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值