2023杭电第四场补题报告 1003 1006 1007 1010 1012

文章介绍了杭电编程竞赛中的几道题目,包括SimpleSetProblem的双指针解决方案和快读优化,PSO的直接公式推导,Guess问题的质因数分解策略,以及KongMingQi和a-bProblem的逻辑推理与排序方法。这些题目涉及到了数据结构、算法优化和数学思维在编程竞赛中的应用。
摘要由CSDN通过智能技术生成

2023杭电第四场补题报告 1003 1006 1007 1010 1012

1003 Simple Set Problem (hdu.edu.cn)

思路

双指针直接暴力扫过去,复杂度O(n),但是卡常数,换了超级快读才ac。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
void solve();
#define re register

inline char nc() {
  static char buf[100000], *p1 = buf, *p2 = buf;
  // static 个人理解为只作用于设定地点的变量,每次返回时数组不变
  //例如:退出函数时,数组存放了1,再次进入函数,数组依然存放着1,所以这句话也可以写成全局变量
  return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2)
             ? EOF
             : *p1++;
  // fread(buf,1,100000,stdin)
  // 读入100000次,长度为1,存入buf中,fread返回值为有效读取字符数
  // p1=读入文件头,p2=读入文件尾,如果p1==p2,证明读完文件
  // buf数组清空时才会继续读入
  //可运用C++的调试查看具体过程
}

//类模板
//可随读入类型的不同,自动变化类型
// fread快读=正常的快读 把getchar改成自定义的读入
template <class T>
inline void read(T &x) {
  x = 0;
  char c = nc();
  bool p = false;
  for (; '0' > c || c > '9'; c = nc()) p |= c == '-';
  for (; '0' <= c && c <= '9'; c = nc()) x = (x << 1) + (x << 3) + (c ^ 48);
  x = p ? -x : x;
}

void write(int x) {
  if (x < 0) putchar('-'), x = -x;
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
  return;
}
signed main() {
  // cin.sync_with_stdio(0);
  // cin.tie(0);
  int T;
  read(T);
  // cin >> T;
  while (T--) {
    solve();
  }
  return 0;
}
#define N 4000100
vector<int> g[N];
void solve() {
  int k;
  read(k);
  vector<int> a;
  // cin >> k;
  for (int i = 0; i < k; i++) {
    g[i].clear();
    int c;
    read(c);
    // cin >> c;
    for (int j = 0; j < c; j++) {
      int x;
      read(x);
      // cin >> x;
      g[i].push_back(x);
    }
    sort(g[i].begin(), g[i].end());
    unique(g[i].begin(), g[i].end());
    for (int z : g[i]) a.push_back(z);
  }
  sort(a.begin(), a.end());
  unique(a.begin(), a.end());
  vector<pair<int, vector<int>>> v(a.size());
  for (int i = 0; i < a.size(); i++) {
    v[i].first = a[i];
  }
  for (int i = 0; i < k; i++) {
    for (int z : g[i]) {
      int id = lower_bound(a.begin(), a.end(), z) - a.begin();
      v[id].second.push_back(i);
    }
  }
  int l = 0, r = 0;
  vector<int> cnt(k);
  int tc = 0;
  int ans = 0x3f3f3f3f3f3f3f3f;
  for (; r < v.size();) {
    while (r < v.size() && tc < k) {
      for (auto z : v[r].second) {
        if (cnt[z] == 0) {
          tc++;
        }
        cnt[z]++;
      }
      r++;
    }
    while (l < r && tc == k) {
      ans = min(ans, abs(v[r - 1].first - v[l].first));
      for (auto z : v[l].second) {
        cnt[z]--;

        if (cnt[z] == 0) {
          tc--;
        }
        ans = min(ans, abs(v[r - 1].first - v[l].first));
      }
      l++;
    }
  }
  write(ans);
  putchar('\n');
}

1006 PSO (hdu.edu.cn)

思路

直接推公式,签到。

代码

#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 ++)  

using namespace std;
 
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
int n,m,k,x,y,a[N],b[N];

void solve() {
	cin >> n;
	if(n != 2)
	printf("%.9lf %.9lf\n",(double)(n-1)/n*2,(double)2); 
	else {
		printf("%.9lf %.9lf\n",(double)(n-1)/n*2,(double)1);
	}
	
}

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

1007 Guess (hdu.edu.cn)

思路

打表找规律,然后发现除了是某个质数的整数次幂之外都是1。需要用到大质数的质因数分解,牺牲精确度换取时间。

代码

#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

using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e8 + 10;
const int mod = 998244353;
typedef pair<int, int> PII;
int n, m;
int a[N];
int primes[N], cnt;  // primes[]存储所有素数
bool st[N];          // st[x]存储x是否被筛掉

int tol;                //质因数的个数,编号为0~tol-1
long long factor[100];  //质因素分解结果(刚返回时是无序的)

const int S = 8;  //随机算法判定次数,一般8~10次就够了

#define re register

inline char nc() {
  static char buf[100000], *p1 = buf, *p2 = buf;
  // static 个人理解为只作用于设定地点的变量,每次返回时数组不变
  //例如:退出函数时,数组存放了1,再次进入函数,数组依然存放着1,所以这句话也可以写成全局变量
  return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2)
             ? EOF
             : *p1++;
  // fread(buf,1,100000,stdin)
  // 读入100000次,长度为1,存入buf中,fread返回值为有效读取字符数
  // p1=读入文件头,p2=读入文件尾,如果p1==p2,证明读完文件
  // buf数组清空时才会继续读入
  //可运用C++的调试查看具体过程
}

//类模板
//可随读入类型的不同,自动变化类型
// fread快读=正常的快读 把getchar改成自定义的读入
template <class T>
inline void read(T &x) {
  x = 0;
  char c = nc();
  bool p = false;
  for (; '0' > c || c > '9'; c = nc()) p |= c == '-';
  for (; '0' <= c && c <= '9'; c = nc()) x = (x << 1) + (x << 3) + (c ^ 48);
  x = p ? -x : x;
}

void write(int x) {
  if (x < 0) putchar('-'), x = -x;
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
  return;
}

int ksm(int a, int b, int p) {
  int ret = 1;
  for (; b; b >>= 1, a = (__int128)a * a % p)
    if (b & 1) ret = (__int128)ret * a % p;
  return ret;
}
bool Miinter_Rabin(int p) {
  if (p < 2) return 0;
  if (p == 2 || p == 3) return 1;
  int d = p - 1, r = 0;
  while (!(d & 1)) ++r, d >>= 1;
  for (int k = 0; k < 10; ++k) {
    int a = rand() % (p - 2) + 2;
    int x = ksm(a, d, p);
    if (x == 1 || x == p - 1) continue;
    for (int i = 0; i < r - 1; ++i) {
      x = (__int128)x * x % p;
      if (x == p - 1) break;
    }
    if (x != p - 1) return 0;
  }
  return 1;
}

int Pointard_Rho(int x) {
  int s = 0, t = 0;
  int c = (int)rand() % (x - 1) + 1;
  int step = 0, goal = 1;
  int val = 1;
  for (goal = 1;; goal <<= 1, s = t, val = 1) {
    for (step = 1; step <= goal; step++) {
      t = ((__int128)t * t + c) % x;
      val = (__int128)val * abs(t - s) % x;
      if (step % 127 == 0) {
        int d = __gcd(val, x);
        if (d > 1) return d;
      }
    }
    int d = __gcd(val, x);
    if (d > 1) return d;
  }
}
void f(int x) {
  if (x < 2) return;
  if (Miinter_Rabin(x)) {
    factor[tol++] = x;
    return;
  }
  int p = x;
  while (p == x) p = Pointard_Rho(x);
  f(x / p);
  f(p);
}

void solve() {
  read(n);
  tol = 0;
  f(n);
  sort(factor, factor + tol);
  set<int> st;
  for (int i = 0; i < tol; i++) {
    // cout << factor[i] << " ";
    st.insert(factor[i]);
  }
  if (st.size() == 1) {
    cout << *st.begin() % mod << "\n";
  } else
    cout << 1 << "\n";
}

signed main() {
  IOS;
  int t = 1;
  read(t);
  for (int i = 1; i <= t; i++) {
    solve();
  }
}

1010 Kong Ming Qi (hdu.edu.cn)

思路

通过模拟小样例猜的结论,证明很复杂,和三元组和群论有关。

代码

#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

using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n, m;
int a[N];

void solve() {
  cin >> n >> m;
  if (n == 1 || m == 1) {
    cout << (n + m - 2) / 2 + 1 << "\n";
  } else {
    if (n % 3 == 0 || m % 3 == 0) {
      cout << 2 << "\n";
    } else {
      cout << 1 << "\n";
    }
  }
}

signed main() {
  IOS;
  int t = 1;
  cin >> t;
  for (int i = 1; i <= t; i++) {
    solve();
  }
}

1012 a-b Problem (hdu.edu.cn)

思路

按和的大小从大到小排序,依次取即可。

代码

#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

using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n;

void solve() {
  cin >> n;
  priority_queue<PII> s1;
  vector<int> v(n + 10);
  vector<PII> ss;
  ss.push_back({0, 0});
  for (int i = 1; i <= n; i++) {
    int x, y;
    cin >> x >> y;
    s1.push({x + y, i});
    ss.push_back({x, y});
  }

  int cnt = n;
  int res = 0;
  while (cnt--) {
    if ((n - cnt) % 2) {
      do {
        auto tmp = s1.top();
        s1.pop();
        int id = tmp.sc;
        if (v[id])
          continue;
        else {
          v[id] = 1;
          res += ss[id].fi;
          break;
        }
      } while (s1.size());
    } else {
      do {
        auto tmp = s1.top();
        s1.pop();
        int id = tmp.sc;
        if (v[id])
          continue;
        else {
          v[id] = 1;
          res -= ss[id].sc;
          break;
        }
      } while (s1.size());
    }
  }
  cout << res << "\n";
}

signed main() {
  IOS;
  int t = 1;
  cin >> t;
  for (int i = 1; i <= t; i++) {
    solve();
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值