This commit is contained in:
HuangHai
2025-08-30 18:35:01 +08:00
commit 1f397eca87
6258 changed files with 1487241 additions and 0 deletions

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,23 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 210;
int b[N];
int n = 200; // 200以内的质数
int main() {
// 初始化标记数组中所有数字都是质数
memset(b, 1, sizeof b);
for (int i = 2; i <= n; i++) {
if (b[i])
for (int j = i * 2; j <= n; j += i) // 倍数都是合数
b[j] = 0;
}
// 输出有哪些质数
for (int 2 = 1; i <= n; i++)
if (b[i])
cout << i << " ";
return 0;
}

View File

@@ -0,0 +1,24 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 210;
int b[N];
int n = 200; // 200以内的质数
int main() {
// 初始化标记数组中所有数字都是质数
memset(b, 1, sizeof b);
// 理论依据:任何非质数,都会有一个因数不会大于他的算术平方根。所以优化后代码:
for (int i = 2; i <= sqrt(n); i++) { // 优化上限n到sqrt(n)
if (b[i])
for (int j = i * 2; j <= n; j += i) // 倍数都是合数
b[j] = 0;
}
// 输出有哪些质数
for (int i = 2; i <= n; i++)
if (b[i])
cout << i << " ";
return 0;
}

View File

@@ -0,0 +1,25 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 210;
int b[N];
int n = 200; // 200以内的质数
int main() {
// 初始化标记数组中所有数字都是质数
memset(b, 1, sizeof b);
// 理论依据:任何非质数,都会有一个因数不会大于他的算术平方根。所以优化后代码:
for (int i = 2; i <= sqrt(n); i++) { // 优化上限n到sqrt(n)
if (b[i])
// 根据观察,每次筛选的时候从这个数的平方开始筛选就可以。
for (int j = i * i; j <= n; j += i) // 倍数都是合数
b[j] = 0;
}
// 输出有哪些质数
for (int i = 2; i <= n; i++)
if (b[i])
cout << i << " ";
return 0;
}

View File

@@ -0,0 +1,42 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 10010;
struct Node {
int id; // 第几个学生
int c, m, e; // 语文 数学 英语
friend bool operator<(Node a, Node b) {
int s1 = a.c + a.m + a.e;
int s2 = b.c + b.m + b.e; // 总分
if (s1 != s2) // 总分不同 总分大的在前
return s1 > s2;
if (a.c + a.m != b.c + b.m) // 语文和数学总分不同 语文和数学总分大的在前
return a.c + a.m > b.c + b.m;
if (max(a.c, a.m) != max(b.c, b.m)) // 语文和数学中较大的一个不同 较大的在前
return max(a.c, a.m) > max(b.c, b.m);
return a.id < b.id; // 语文和数学中较大的一个相同 录入顺序小的在前
}
} a[N];
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i].c >> a[i].m >> a[i].e; // 同学的语文、数学、外语成绩
a[i].id = i; // 同学的录入顺序
}
sort(a + 1, a + n + 1);
// 5 3 2 4 1
// 100 100 98 98 97
for (int i = 1; i <= n; i++) {
// 到a数组中去查找
for (int j = 1; j <= n; j++) {
if (a[j].id == i) {
cout << j << endl;
break;
}
}
}
return 0;
}

View File

@@ -0,0 +1 @@
https://blog.csdn.net/weixin_40204595/article/details/105405170

Binary file not shown.

View File

@@ -0,0 +1,39 @@
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL n;
int idx;
int main() {
cin >> n;
// 拆分合数
for (LL p = 2; p * p <= n; p++) { // 2~sqrt(n)
if (n % p) // 如果p不是n的因数
continue;
idx++; // 第几个因数
int cnt = 0; // p的指数个数
while (n % p == 0) {
cnt++; // 有几个p因数
n /= p; // 除掉
}
if (idx > 1)
cout << " * ";
cout << p;
if (cnt > 1)
cout << "^" << cnt;
}
// 质数
if (n > 1) {
if (++idx > 1)
cout << " * ";
cout << n;
}
return 0;
}

View File

@@ -0,0 +1,36 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 510;
int n;
int t[N], r[N];
int ans;
/*
此题采用贪心算法,从最后一个时段开始,选择在该时段内完成有奖励的小游戏中找奖励最大的完成,
时间复杂度为O(N^2)
*/
int main() {
cin >> n;
for (int i = 1; i <= n; i++)
cin >> t[i];
for (int i = 1; i <= n; i++)
cin >> r[i];
// 从最后一个时段开始枚举
for (int i = n; i >= 1; i--) {
int k = 0; // 找到i时段之内最大分值位置
int m = 0; // 最大分值
for (int j = 1; j <= n; j++) {
if (t[j] >= i && r[j] > m) {
m = r[j];
k = j;
}
}
if (k != 0) { // 如果找到了
ans += r[k]; // 加分
r[k] = 0; // 清零,防止重复
}
}
cout << ans << endl;
return 0;
}

View File

@@ -0,0 +1,38 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 510;
/*
贪心思路:
先将游戏按分值从大到小排列,然后给最大分值的游戏安排在时效内尽可能晚的时段完成,
安排完所有游戏,对于能安排的游戏,计分,即为答案
7
4 2 4 3 1 4 6
70 60 50 40 30 20 10
*/
int n;
struct Node {
int T, R;
} a[N];
bool cmp(Node x, Node y) { return x.R > y.R; }
bool b[N];
int sum;
int main() {
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i].T;
for (int i = 0; i < n; i++)
cin >> a[i].R;
sort(a, a + n, cmp);
for (int i = 0; i < n; i++) // 小游戏
for (int t = a[i].T - 1; t >= 0; t--) // 时间段
if (!b[t]) { // 是不是被占用
b[t] = true;
sum += a[i].R;
break;
}
cout << sum << endl;
return 0;
}

Binary file not shown.

View File

@@ -0,0 +1,5 @@
2 4
1
4
5
9

View File

@@ -0,0 +1,12 @@
16 11
1
2
4
8
16
32
64
128
256
512
1024

View File

@@ -0,0 +1,33 @@
#include <bits/stdc++.h>
using namespace std;
set<int> s; // 幸运数集合
const int N = 1e6;
int main() {
int a, T;
cin >> a >> T;
// 筛法,枚举出1e6以下所有的超级幸运数
for (int i = 1; i * i <= N; i++)
if (i * i >= a) {
// 枚举超级幸运数的倍数
for (int j = 1; i * i * j <= N; j++)
s.insert(i * i * j);
}
while (T--) {
int x;
cin >> x;
// 判断x是不是超级幸运数或者幸运数
if (s.count(x))
cout << "Lucky" << endl;
else {
// 找出第一个比它大的幸运数
for (int i = x + 1;; i++)
if (s.count(i)) {
cout << i << endl;
break;
}
}
}
return 0;
}

View File

@@ -0,0 +1,45 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 1000010;
int a[N];
int ans;
/*
3
1 2 3
答案:2
5
5 6 2 10 13
答案:
8
*/
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
// 很明显,1e6的平方级算法会TLE,但40%的测试点是可以过的
set<int> s; // 哪个数字已经被淘汰掉了
for (int i = 31; i >= 0; i--) {
int cnt = 0;
for (int j = 1; j <= n; j++) { // 遍历所有数字
if (s.count(j) == 0 &&
a[j] >> i & 1) // 如果a[j]这个数字没有被淘汰掉,并且这个数字的第i位是1
cnt++;
}
if (cnt >= 2) {
// 如果此位存在1两个以上,那么此位是有效数位,所以此位是0的会被淘汰
for (int j = 1; j <= n; j++)
if (!(a[j] >> i & 1))
s.insert(j);
// 记录&的累加值
ans = ans + (1 << i);
}
}
cout << ans << endl;
return 0;
}

View File

@@ -0,0 +1,30 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 1000010;
int a[N];
int ans;
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
set<int> _set; // 哪个数字已经被淘汰掉了
for (int i = 30; i >= 0; i--) {
int cnt = 0; // 枚举每个数字的二进制数位,由高到低
for (int j = 1; j <= n; j++) {
if (a[j] >> i & 1 && !_set.count(j))
cnt++;
}
if (cnt >= 2) {
for (int j = 1; j <= n; j++)
if (!(a[j] >> i & 1))
_set.insert(j);
ans = ans + (1 << i);
}
}
cout << ans << endl;
return 0;
}

Binary file not shown.

View File

@@ -0,0 +1,81 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 10010;
/*
6
140 140 150
140 149 140
148 141 140
141 148 140
145 145 139
0 0 0
*/
struct Node {
int id; // 输入序号
int pm; // 排名
int yw; // 语文
int sx; // 数学
int yy; // 英语
} a[N];
int b[N];
int cmp(Node a, Node b) {
// 1、总分谁多谁靠前
if (a.yw + a.sx + a.yy != b.yw + b.sx + b.yy)
return a.yw + a.sx + a.yy > b.yw + b.sx + b.yy; // a 大返回1,b大返回0
// 2、如果总分相等,那么语文和数学谁多谁靠前
if (a.yw + a.sx != b.yw + b.sx)
return a.yw + a.sx > b.yw + b.sx;
// 3、如果仍相同,则⽐较语⽂和数学两科的最⾼分,⾼者靠前;
int x = max(a.yw, a.sx);
int y = max(b.yw, b.sx);
if (x != y)
return x > y;
// 4、如果仍相同,则⼆⼈并列。
return 2;
}
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i].yw >> a[i].sx >> a[i].yy;
a[i].id = i; // 输入序号
}
// 冒泡排序
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++) {
if (cmp(a[i], a[j]) == 0)
// 如果a[i]小于a[j] 则交换a[i],a[j],使得大的在前
swap(a[i], a[j]);
}
// 输出一下看看
for (int i = 1; i <= n; i++) {
a[i].pm = i;
// cout << "PaiMing=" << a[i].pm << " id=" << a[i].id << " " << endl;
}
// a[1].pm = 1;
// 由于并列的原因,a数组还需要处理一下
for (int i = 2; i <= n; i++)
// 和前一个对比cmp,如果一样的话,修改自己的排名和前一位的排名一致
if (cmp(a[i], a[i - 1]) == 2)
a[i].pm = a[i - 1].pm;
else
a[i].pm = i;
// 输出一下看看
// for (int i = 1; i <= n; i++) {
// cout << "PaiMing=" << a[i].pm << " id=" << a[i].id << " " << endl;
// }
// 记录第几个录入的是第几名
for (int i = 1; i <= n; i++)
b[a[i].id] = a[i].pm;
for (int i = 1; i <= n; i++)
cout << b[i] << endl;
return 0;
}

View File

@@ -0,0 +1,51 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int primes[N], cnt;
bool st[N];
void get_primes(int n) {
for (int i = 2; i <= n; i++) {
if (!st[i])
primes[cnt++] = i;
for (int j = 0; primes[j] * i <= n; j++) {
st[primes[j] * i] = true;
if (i % primes[j] == 0)
break;
}
}
}
int getMx(int x) {
int mx = 0;
// 1、如果x是质数,那么它的最大质数因子就是它自己
if (!st[x])
return x;
// 2、枚举x的所有可能的质数小因子
for (int i = 0; primes[i] * primes[i] <= x; i++) { // 2*2*7=28
while (x % primes[i] == 0) { // primes[i]是小质因子
mx = max(mx, primes[i]); // 小质数因子也可能是最大质数因子,比如8=2*2*2
if (!st[x / primes[i]]) // 也可能大因子是质数
mx = max(mx, x / primes[i]); // 大质数因子就会成为最大质数因子
x /= primes[i];
}
}
return mx;
}
int main() {
int n, b;
cin >> n >> b;
get_primes(N);
for (int i = 1; i <= 20; i++)
cout << getMx(i) << " ";
int ans = 0;
for (int i = 1; i <= n; i++) {
if (getMx(i) <= b)
ans++;
}
cout << ans << endl;
return 0;
}

Binary file not shown.

View File

@@ -0,0 +1,44 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int a[N][N]; // 原始数组
int s[N][N]; // 二维前缀和数组
int get(int x1, int y1, int x2, int y2) {
return s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1];
}
/*
4 5 5
00000
01111
00011
00011
参考答案:6
*/
int main() {
int n, m, k;
cin >> n >> m >> k;
char c;
// 输入原始数组
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> c, a[i][j] = c - '0';
// 构建二维前缀和数组
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
// 遍历每个可能的矩形,计算此矩形的二维前缀和,要求大于等k,求得最小的长乘以宽的值,也就是最小矩形大小
int ans = 1e9;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
for (int x = i; x <= n; x++)
for (int y = j; y <= m; y++)
if (get(i, j, x, y) >= k)
ans = min(ans, (x - i + 1) * (y - j + 1));
if(ans==1e9) ans=0;
cout << ans << endl;
return 0;
}

View File

@@ -0,0 +1,39 @@
#include <bits/stdc++.h>
using namespace std;
bool isPrime(int x) {
for (int i = 2; i <= x / i; i++) {
if (x % i == 0)
return false;
}
return true;
}
bool isLucky(int x) {
// 将数字x分解质因数,并且记录质因数的个数,如果质因数个数为2,并且不能重复,则返回true,否则返回false
int cnt = 0;
for (int i = 2; i <= x; i++) {
if (x % i == 0 && isPrime(i))
cnt++;
}
return cnt == 2;
}
/*
3
7 12 30
参考答案:0 1 0
*/
int main() {
int n;
cin >> n;
while (n--) {
int x;
cin >> x;
if (isLucky(x))
cout << 1 << endl;
else
cout << 0 << endl;
}
return 0;
}

Binary file not shown.

View File

@@ -0,0 +1,30 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N], c[N];
/*
2 2
9 9
1 -1
参考答案:10
*/
int main() {
int n, m;
cin >> n >> m;
int mx = -1e9;
for (int i = 1; i <= n; i++) {
cin >> c[i];
mx = max(mx, c[i]);
}
for (int i = 1; i <= m; i++)
cin >> a[i];
for (int i = 1; i <= m;i++) { // 注意特殊情况,比如n=1,此时如果a[i]<0,那么就只能是减掉
if (n == 1 || a[i] > 0)
mx += a[i];
}
cout << mx << endl;
return 0;
}

View File

@@ -0,0 +1,71 @@
#include <bits/stdc++.h>
using namespace std;
// 欧拉筛
const int N = 1e5 + 10;
int primes[N], cnt; // primes[]存储所有素数
bool st[N]; // st[x]存储x是否被筛掉
void get_primes(int n) {
for (int i = 2; i <= n; i++) {
if (!st[i])
primes[cnt++] = i;
for (int j = 0; primes[j] * i <= n; j++) {
st[primes[j] * i] = true;
if (i % primes[j] == 0)
break;
}
}
}
/*
3
6 188 9999
参考答案
2
4
-1
*/
int main() {
get_primes(N);
int T;
cin >> T;
while (T--) {
int h;
cin >> h;
// 如果h质数,则一次魔法攻击就可以解决问题,答案是1,continue表示本组测试用例处理完成
if (!st[h]) {
cout << 1 << endl;
continue;
}
// 如果没有干掉,需要找到最大的质数扣除掉
int mx = 0;
for (int i = 0;; i++) {
if (primes[i] > h)
break;
else
mx = max(mx, primes[i]);
}
// 扣除掉最大质数
h -= mx;
int ans = 1;
// 开始物理攻击
int base = 1;
for (int i = 1;; i++) {
ans++;
h -= base;
if (h < 0) {
cout << -1 << endl;
break;
}
if (h == 0) {
cout << ans << endl;
break;
}
base *= 2;
}
}
return 0;
}

Binary file not shown.

View File

@@ -0,0 +1,40 @@
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
/*
5^6= 5^1* 5^2 * 5^3
x=6 tmp=1 ans=1 -->x=6-1=5
x=5 tmp=2 ans=2 -->x=5-2=3
x=3 tmp=3 ans=3 -->x=3-3=0
*/
LL calc(LL x) {
int ans = 0;
for(int i=1;;i++){
if(x>=i){
ans++;
x-=i;
}else
break;
}
return ans;
}
int main() {
// cout << calc(4) << endl; // 2^4=16 --> 2+4 +8
LL n;
cin >> n;
LL ans = 0;
for (LL i = 2; i * i <= n; i++) {
if (n % i == 0) {
int cnt = 0;
while (n % i == 0) {
cnt++;
n /= i;
}
ans += calc(cnt);
}
}
if (n != 1)
ans += 1; // 剩余质数
cout << ans << "\n";
//return 0;
}

View File

@@ -0,0 +1,54 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
typedef long long LL;
int n, m; // n种武器,m种加强材料
vector<int> c[N]; // c[i][j]表示可以强化第i种武器的材料,修改花费
LL ans = LONG_LONG_MAX; // 答案,预求最小先设最大
/**
* 计算最终1号武器加强材料的数量为aim时,需要花费的费用
*/
LL calc(int aim) {
int a1 = c[1].size(); // 1号武器已有的加强材料数量
LL res = 0;
vector<int> tmp;
for (int i = 2; i <= n; i++) { // 遍历2号武器到n号武器
// 当前i号武器需要去掉多少个加强材料,也就是需要付费购买多少个加强材料
int buy = max((int)c[i].size() - aim + 1, 0);
for (int j = 0; j < buy; j++)
res += (LL)c[i][j]; // 这些钱不得不花
a1 += buy; // 通过购买,1号武器的加强材料数量上升了!
// 对于第i种武器,没有购买的加强材料汇总到tmp数组中,因为可能存在
for (int j = buy; j < c[i].size(); j++)
tmp.push_back(c[i][j]);
}
// 所有没动过的材料进行由小到大排序
sort(tmp.begin(), tmp.end());
// 如果数量不足,还需要在这些没动过的材料中取一些
for (int i = 0; i < aim - a1; i++)
res += (LL)tmp[i];
return res;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("20241202.in", "r", stdin);
#endif
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int p, cc;
cin >> p >> cc;
c[p].push_back(cc);
}
for (int i = 1; i <= n; i++)
sort(c[i].begin(), c[i].end()); // 每种武器的加强材料按价格由小到大排序
// 枚举最终第1种武器的加强材料数量
for (int i = max((int)c[1].size(), 1); i <= m; i++)
ans = min(ans, calc(i)); // 计算此时需要花费的金额,最小值就是答案
cout << ans << endl;
return 0;
}

View File

@@ -0,0 +1,5 @@
4 4
1 1
2 1
3 1
3 2

View File

@@ -0,0 +1,43 @@
## 一、 前导知识
#### 优先队列重载小于号
``` cpp
#include <bits/stdc++.h>
using namespace std;
struct Node {
int val;
// 自定义排序方法1
// bool operator<(const Node &b) const {
// return val < b.val;
// }
// 自定义排序方法2
// 重载小于号,如果a.val<b.val,则返回true,也就是a比b小,但是,由于优先队列是大顶堆,大的先出,所以b先出队列
friend bool operator<(Node a, Node b) {
return a.val < b.val;
}
};
priority_queue<Node> q;
int main() {
Node a;
a.val = 1;
q.push(a);
Node b;
b.val = 2;
q.push(b);
cout << q.top().val << endl;
// 输出结果:2
// 解释:由于优先队列是大顶堆,所以大的先出,所以b先出队列
// 加快读入
return 0;
}
```
在此处定义一个优先队列**大顶堆**:`priority_queue pri`;
如果要按照以$val$的值进行 **从小到大** 排列,操作如上。重载$<$操作符。
意思是如果$a.val < b.val$成立,那么结构体`Node a < Node b`。
**解释**:由于优先队列大顶堆是按照从大到小排列,所以结构体$b$会排列到$a$之前。

View File

@@ -0,0 +1,147 @@
```c++
void removeElements(LinkedNode* head, int val) {
if (head == nullptr) {
return;
}
LinkedNode* cur;
LinkedNode* dummyHead = new LinkedNode(0); // 虚拟头节点
dummyHead->next = head; // 将虚拟头节点连接到原链表
cur = dummyHead; // 从虚拟头节点开始遍历
while(cur->next != nullptr) {
if(cur->next->val == val) {
LinkedNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
tmp = nullptr;
}
else {
cur = cur->next;
}
}
head = dummyHead->next;
delete dummyHead;
dummyHead = nullptr;
}
A. dummyHead->next = head; cur = dummyHead;
B. dummyHead->next = head->next; cur = dummyHead;
C. dummyHead->next = head; cur = dummyHead->next;
D. dummyHead->next = head->next; cur = dummyHead->next;
```
这样可以正确处理所有情况,包括:
- 删除普通节点
- 删除头节点
- 删除连续节点
- 删除尾节点
### 此题目的重占在于操作的是:cur->next
我来用 ASCII 图解释这个过程,假设我们要删除值为 $3$ 的节点。
原始链表:
```
1 -> 3 -> 3 -> 2 -> 3 -> 6
```
1 创建虚拟头节点并连接(选项 $A$):
```
dummyHead(0) -> 1 -> 3 -> 3 -> 2 -> 3 -> 6
^
|
cur
```
2 遍历过程:
第一步:$cur->next$ (值为1) ≠ 3,移动 $cur$
```
dummyHead(0) -> 1 -> 3 -> 3 -> 2 -> 3 -> 6
^
|
cur
```
第二步:$cur->next$ (值为3) = 3,删除节点
```
dummyHead(0) -> 1 -> 3 -> 3 -> 2 -> 3 -> 6
^ |
| ×
cur |
+----+
```
删除后:
```
dummyHead(0) -> 1 -> 3 -> 2 -> 3 -> 6
^
|
cur
```
继续类似操作,最终结果:
```
dummyHead(0) -> 1 -> 2 -> 6
```
如果是其他选项:
选项 B (dummyHead->next = head->next; cur = dummyHead):
```
原始: 1 -> 3 -> 3 -> 2 -> 3 -> 6
变成:
dummyHead(0) -> 3 -> 3 -> 2 -> 3 -> 6 // 丢失了节点1
^
|
cur
```
选项 C (dummyHead->next = head; cur = dummyHead->next):
```
dummyHead(0) -> 1 -> 3 -> 3 -> 2 -> 3 -> 6
^
|
cur // cur 从1开始,无法处理第一个节点
```
选项 D (dummyHead->next = head->next; cur = dummyHead->next):
```
dummyHead(0) -> 3 -> 3 -> 2 -> 3 -> 6
^
|
cur // 既丢失了节点1,又无法处理第一个节点
```
所以选项 $A$ 是正确的,因为:
保留了完整的原始链表
cur 从虚拟头节点开始,可以处理所有节点
通过 cur->next 来判断和删除节点,操作更安全

View File

@@ -0,0 +1 @@
$\phi(p) = p - 1$

Binary file not shown.

View File

@@ -0,0 +1,20 @@
#include <bits/stdc++.h>
using namespace std;
const int p = 1e9 + 7;
// 快速幂
int qmi(int a, int b) {
int r = 1; // 初始化结果为1
a %= p; // 先取模防止溢出
while (b) { // 当指数不为0时循环
if (b & 1) // 如果当前二进制位是1
r = (1LL * r * a) % p; // 累乘当前基数
a = (1LL * a * a) % p; // 基数平方
b >>= 1; // 右移一位(相当于除以2)
}
return r;
}
int main() {
// (10)2=1010
cout << qmi(2, 10) << endl;
return 0;
}

View File

@@ -0,0 +1,36 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
typedef long long LL;
int n;
LL b[N], c[N], d[N];
/*
关键点解释:
差价数组 d 的排序是升序排列,所以后 n 个元素是最大的
通过选择最大的 n 个差价,确保我们最大化改卖给小 C 带来的收益提升
最终总收益 = 全选小 B 的收益 + 最优的 n 个改卖带来的收益提升
*/
LL ans;
int main() {
freopen("T1.in", "r", stdin);
cin >> n;
for (int i = 1; i <= 2 * n; i++)
cin >> b[i];
for (int i = 1; i <= 2 * n; i++)
cin >> c[i];
// 初始化为全选小 B 的总收入
for (int i = 1; i <= 2 * n; i++)
ans += b[i];
// 计算每个物品改卖给小 C 的差价
for (int i = 1; i <= 2 * n; i++)
d[i] = c[i] - b[i];
// 排序后取最大的 n 个差价(排序后后半段是最大的)
sort(d + 1, d + 2 * n + 1);
for (int i = n + 1; i <= 2 * n; i++)
ans += d[i];
cout << ans << endl;
return 0;
}

View File

@@ -0,0 +1,3 @@
2
6 7 9 9
1 2 10 12

View File

@@ -0,0 +1,37 @@
#include <bits/stdc++.h>
using namespace std;
#define int long long
int a, p;
// 快速幂
int qmi(int a, int b, int p) {
int res = 1;
while (b) {
if (b & 1)
res = res * a % p;
b >>= 1;
a = a * a % p;
}
return res;
}
void solve() {
int a, p;
cin >> a >> p;
int phi = p - 1;
for (int i = 2; i * i <= phi; i++) {
if (phi % i == 0) {
if (qmi(a, i, p) == 1 || qmi(a, phi / i, p) == 1) {
puts("No");
return;
}
}
}
puts("Yes");
}
signed main() {
int T;
cin >> T;
while (T--)
solve();
}

View File

@@ -0,0 +1,4 @@
3
3 998244353
5 998244353
7 998244353

View File

@@ -0,0 +1,72 @@
### 一、基础知识
$$ a^x \equiv 1 \pmod{p} $$
这句话是数论中的一个概念,表示:
1. $ a $ 和 $ p $ 是整数,且 $ p $ 是一个正整数
2. $ a^x $ 表示 $ a $ 的 $ x $ 次方
3. 当 $ a^x $ 除以 $ p $ 时,余数为 1
换句话说,$ a^x - 1 $ 能被 $ p $ 整除。
在数论中,这个表达式经常出现在以下场景中:
1. **阶($Order$)**:当 $ a $ 和 $ p $ 互质时,满足这个等式的最小正整数 $ x $ 称为 $ a $ 模 $ p $ 的阶。
2. **费马小定理**:当 $ p $ 是质数且 $ a $ 不被 $ p $ 整除时,有 $ a^{p-1} \equiv 1 \pmod{p} $
3. **原根**:如果 $ a $ 的阶等于 $ p-1 $,则 $ a $ 称为模 $ p $ 的一个原根
这个表达式在密码学(如$RSA$算法)、数论和计算机科学中都有重要应用。
### 二、本题求解
显然:$a^{xy}=(a^x) ^y$
$2^{6}={2^2}^3$
假设 $a ^x ≡1\ (\ mod\ p)$,则有 $a^{xy} =(a ^x) ^y ≡1 ^y ≡1\ (mod\ p)$。
> 上面这句话展示了模运算中指数运算的一个重要性质。让我们逐步理解:
已知条件:$a^x ≡ 1\ (\text{mod}\ p)$
这意味着$a^x$除以$p$的余数是1
或者说$a^x - 1$能被$p$整除
推导过程:
$a^{xy} = (a^x)^y$
由于$a^x ≡ 1\ (\text{mod}\ p)$,我们可以将其代入
$(a^x)^y ≡ 1^y\ (\text{mod}\ p)$
而$1^y = 1$,所以最终得到$a^{xy} ≡ 1\ (\text{mod}\ p)$
**理解**
这个性质表明,如果一个数的某次方模$p$等于1,那么它的任意倍数次方模$p$也等于1
这在数论和密码学中非常有用,特别是在研究循环群和原根时
例如,在$RSA$加密算法中,这个性质被用来证明解密过程的正确性
> **举例说明**:
假设$a = 2$, $p = 7$
$2^3 = 8 ≡ 1\ (\text{mod}\ 7)$
那么$2^{3×2} = 2^6 = 64 ≡ 1\ (\text{mod}\ 7)$
$2^{3×3} = 2^9 = 512 ≡ 1\ (\text{mod}\ 7)$
这个例子验证了上述结论的正确性
因此,原命题是正确的,它展示了模运算中指数运算的一个重要性质。
>
所以我们可以 $O(\sqrt{p})$ 分解 $p−1$ 的质因数,然后检查 $p−1$ 的每一个因数 $f$ 是否满足 $a^f ≡1(mod\ p)$,如果有任意一个因数满足上述条件,直接输出 $No$。如果所有因数均不满足,输出 $Yes$。
### 三、 原根判断算法解析
#### 原根的定义
在模 `p` 的情况下,`a` 是原根当且仅当 `a` 的阶数等于 `p-1`。阶数是指最小的正整数 `k` 使得:
\[ a^k \equiv 1 \mod p \]
#### 代码的核心思想
1. **分解 `p-1` 的质因数**:代码通过遍历 `2` 到 `sqrt(p-1)` 来找到 `p-1` 的所有质因数。
2. **检查阶数**:对于每个质因数 `i`,检查是否:
\[ a^i \equiv 1 \mod p \]
或
\[ a^{(p-1)/i} \equiv 1 \mod p \]
如果满足,说明 `a` 的阶数小于 `p-1`,因此 `a` 不是原根。
#### 为什么这个方法有效?
- **阶数的性质**:如果 `a` 的阶数小于 `p-1`,那么它必须是 `p-1` 的某个真因数。因此,我们只需要检查 `p-1` 的所有质因数对应的幂次是否等于 1。
- **快速幂**:`qmi` 函数用于高效计算模幂,确保算法的时间复杂度在可接受范围内。

View File

@@ -0,0 +1,20 @@
#include <bits/stdc++.h>
using namespace std;
#define int long long
// 快速幂
int qmi(int a, int b, int p) {
int res = 1;
while (b) {
if (b & 1)
res = res * a % p;
b >>= 1;
a = a * a % p;
}
return res;
}
signed main() {
cout << qmi(3, 5, 1e+7) << endl;
return 0;
}

View File

@@ -0,0 +1,39 @@
#include <bits/stdc++.h>
using namespace std;
// 判断是不是闰年
bool isRun(int year) {
return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
}
// 获取每个月的天数
int getDays(int year, int month) {
int days[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
return days[month] + (month == 2 && isRun(year));
}
// 获取星期几
int getXq(int year, int month, int day) {
// 我们知道2024年1月1号是星期一
// year>=2024
// 计算2024年1月1号到year年month月day日的天数 2025
int days = 0;
for (int i = 2024; i < year; i++)
days += 365 + isRun(i);
for (int i = 1; i < month; i++)
days += getDays(year, i);
days += day;
return days % 7;
}
int main() {
// 初始化2024年1月1号至2025年12月31号
for (int year = 2024; year <= 2025; year++) {
for (int month = 1; month <= 12; month++) {
int days = getDays(year, month);
for (int day = 1; day <= days; day++)
cout << year << " " << month << " " << day << " "
<< getXq(year, month, day) << endl;
}
}
return 0;
}

View File

@@ -0,0 +1,38 @@
#include <bits/stdc++.h>
const int N = 5e5 + 10;
using namespace std;
int n, a, b, mx;
int w[N];
bool check(int mid) {
int sum = 0;
for (int i = 0; i < n; i++) {
int re = w[i] - (mid * a);
if (re > 0)
sum += re / b + (re % b != 0); // 整除则为 re/b,否则是re/b+1
}
return sum <= mid; // 如果sum小于mid,表示mid长的时间足够用
}
int main() {
cin >> n >> a >> b;
mx = -1;
for (int i = 0; i < n; i++) {
cin >> w[i];
mx = max(mx, w[i]); // 找出湿度最大值
}
int l = 1, r = mx / a + (mx % a != 0);
// r是最大湿度除以每分钟自然干的速度,也就是全指望自然干的时间
while (l < r) {
int mid = (l + r) >> 1;
if (check(mid))
r = mid;
else
l = mid + 1;
}
printf("%d\n", r);
return 0;
}

View File

@@ -0,0 +1,26 @@
#include <bits/stdc++.h>
using namespace std;
// https://www.luogu.com.cn/problem/P1843
priority_queue<int> q; // 每次很方便地找到最大值,默认是大顶堆
int n, a, b;
int ans;
int main() {
cin >> n >> a >> b; // 衣服数目,自然晒干,烘干机晒干
for (int i = 1; i <= n; i++) { // 第 i 件衣服的湿度为 w[i]
int w;
cin >> w;
q.push(w);
}
int mx = q.top();
q.pop(); // 每次考虑最湿的衣服就可以了
while (mx > ans * a) { // 如果现在湿度最大的衣服,它在规定时间ans的情况下,自然就可以干了,那就是找到了第一个最小的ans答案
ans++; // 增加1分钟,继续尝试看看是不是可以完成所有衣服的烘干
mx -= b; // 我们默认的贪心策略是挑湿度高的先烘干,所以,烘干机肯定先给湿度最高的衣服使用
q.push(mx);
mx = q.top();
q.pop(); // 重新更新,继续使用
}
cout << ans << endl;
return 0;
}

34
GESP/Level5/Sample.cpp Normal file
View File

@@ -0,0 +1,34 @@
#include <bits/stdc++.h>
using namespace std;
int main() {
string a = "pple";
string b = "apple";
int cnt = 0;
if (a.size() > b.size())
swap(a, b);
if (a.size() - b.size() > 1)
return -1;
// 保证a是短串,b是长串
int p = 0;
for (int i = 0; i < a.size();) {
// 遍历短串中每一个char
// 此时,长串中的位置是p
if (a[i] != b[p]) {
// 对不上的时候,p指针移动一位
p++;
cnt++;
if (cnt > 1)
return -1;
} else {
// 对上的时时候,p指针与i指针同步移动
p++;
i++;
}
}
return 0;
}

10
GESP/Level5/Sample.in Normal file
View File

@@ -0,0 +1,10 @@
3
3
aa
ac
de
2
aac
bc
1
gesp

47
GESP/Level5/Sample2.cpp Normal file
View File

@@ -0,0 +1,47 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 510;
string s[N];
bool check(string x) {
for (int i = 1; i < x.size(); i++)
if (x[i] < x[i - 1])
return false;
return true;
}
int main() {
freopen("Sample.in", "r", stdin);
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
int res = 1;
for (int i = 1; i <= n; i++) {
cin >> s[i];
if (!check(s[i]))
res = 0;
}
if (res == 0) {
cout << 0 << endl;
continue;
}
sort(s + 1, s + n + 1);
for (int i = 2; i <= n; i++) {
// 当前串的头
char head = s[i][0];
// 前一个串的尾巴
char tail = s[i - 1][s[i - 1].size() - 1];
if (head < tail) {
res = 0;
break;
}
}
cout << res << endl;
}
return 0;
}

33
GESP/Level5/Test.cpp Normal file
View File

@@ -0,0 +1,33 @@
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int N = 1e5 + 10;
typedef long long LL;
int n;
LL b[N], c[N];
struct Node{
int cha;
int id;
} d[N];
int cmp(Node a,Node b){
return a.cha < b.cha;
}
int ans = 0;
int main() {
cin >> n;
for (int i = 1; i <= 2 * n; i++)
cin >> b[i];
for (int i = 1; i <= 2 * n; i++)
cin >> c[i];
for (int i = 1; i <= 2 * n; i++)
d[i].cha = c[i] - b[i],d[i].id = i;
sort(d+1,d+1+2*n,cmp);
for (int i = n+1; i <= 2 * n;i++){
ans += c[d[i].id];
}
for (int i = 1; i <= n;i++){
ans += b[d[i].id];
}
cout << ans << endl;
return 0;
}

27
GESP/Level5/Test2.cpp Normal file
View File

@@ -0,0 +1,27 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int b[N], c[N], d[N];
int main() {
int n;
cin >> n;
int sum = 0;
for (int i = 1; i <= 2 * n; i++) {
cin >> b[i];
sum += b[i];
}
for (int i = 1; i <= 2 * n; i++)
cin >> c[i];
for (int i = 1; i <= 2 * n; i++)
d[i] = c[i] - b[i];
sort(d + 1, d + 2 * n + 1);
for (int i = n + 1; i <= 2 * n; i++)
sum += d[i];
cout << sum;
cin >> n;
}

36
GESP/Level5/Test3.cpp Normal file
View File

@@ -0,0 +1,36 @@
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
struct Node {
int id; // 哪个物品
int cha; // 差值
} a[N];
int cmp(Node a, Node b) { return a.cha < b.cha; }
int b[N], c[N];
LL sum;
int main() {
int n;
cin >> n;
for (int i = 1; i <= 2 * n; i++)
cin >> b[i];
for (int i = 1; i <= 2 * n; i++)
cin >> c[i];
for (int i = 1; i <= 2 * n; i++) {
a[i].id = i;
a[i].cha = c[i] - b[i];
}
sort(a + 1, a + 2 * n + 1, cmp);
for (int i = 1; i <= n; i++)
sum += b[a[i].id];
for (int i = n + 1; i <= 2 * n; i++)
sum += c[a[i].id];
cout << sum;
return 0;
}

24
GESP/Level5/new.cpp Normal file
View File

@@ -0,0 +1,24 @@
//欧拉筛
const int N = 1e5 + 10;
int primes[N], cnt; // primes[]存储所有素数
bool st[N]; // st[x]存储x是否被筛掉
void get_primes(int n) {
for (int i = 2; i <= n; i++) {
if (!st[i]) primes[cnt++] = i;
for (int j = 0; primes[j]*i <= n; j++) {
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
void get_primes(int n){
for (int i = 2;i<=n;i++){
if(!st[i])
primes[cnt++] = i;
for (int j = 0; primes[j] * i <= n;j++){
st[primes[j] * i] = true;
if(i%primes[j]==0)
break;
}
}
}

View File

@@ -0,0 +1 @@
https://blog.csdn.net/lan_in/article/details/136913162