记录43
#include<bits/stdc++.h>
using namespace std;
int f(int len){
int a=1;
while(len--) a*=10;
return a;
}
int main(){
int n,q,a[1010]={},len,m;
cin>>n>>q;
for(int i=0;i<n;i++) cin>>a[i];
sort(a,a+n);
while(q--){
bool flag=1;
cin>>len>>m;
for(int i=0;i<n;i++){
int t=a[i]%f(len);
if(t==m){
cout<<a[i]<<endl;
flag=0;
break;
}
}
if(flag) cout<<-1<<endl;
}
return 0;
}
题目传送门
https://www.luogu.com.cn/problem/P3955
突破点
如果一本书的图书编码恰好以读者的需求码结尾,那么这本书就是这位读者所需要的
👉处理数字后几位
如果存在第 i 个读者所需要的书,则在第 i 行输出第 i 个读者所需要的书中图书编码最小的那本书的图书编码,否则输出 −1。
👉数字有大小顺序
思路
- 写一个可以处理指定后几位数的函数
- 将图书编码进行排序
- 寻找结尾符合的数字编码
代码简析
#include<bits/stdc++.h>
using namespace std;
int f(int len){
int a=1;
while(len--) a*=10;
return a;
}
int main(){
int n,q,a[1010]={},len,m;
cin>>n>>q;
for(int i=0;i<n;i++) cin>>a[i];
sort(a,a+n);
...
return 0;
}
f 函数 👉 处理编码的尾巴
说明:数字的尾巴就是后几位,%10得到后一位,%100得到后两位
a 数组 👉 存图书编码
sort()函数 👉 图书编码进行一个从小到大排序
#include<bits/stdc++.h>
using namespace std;
int f(int len){
int a=1;
while(len--) a*=10;
return a;
}
int main(){
int n,q,a[1010]={},len,m;
cin>>n>>q;
for(int i=0;i<n;i++) cin>>a[i];
sort(a,a+n);
while(q--){
bool flag=1;
cin>>len>>m;
for(int i=0;i<n;i++){
int t=a[i]%f(len);
if(t==m){
cout<<a[i]<<endl;
flag=0;
break;
}
}
if(flag) cout<<-1<<endl;
}
return 0;
}
while循环 👉 对每个长度还有结尾进行输入
flag 👉 默认没找到
for循环 👉 输入后对所有的图书编码的后几位进行一个比较
找到后输出,然后修改flag并退出不用比较了,接着输入下一个数据
注意:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,q,a[1010]={},len,m;
cin>>n>>q;
for(int i=0;i<n;i++) cin>>a[i];
sort(a,a+n);
while(q--){
bool flag=1;
cin>>len>>m;
for(int i=0;i<n;i++){
int t=a[i]%int(pow(10,len));//pow返回double类型
if(t==m){
cout<<a[i]<<endl;
flag=0;
break;
}
}
if(flag) cout<<-1<<endl;
}
return 0;
}
如果使用pow函数,必须进行int强转,因为不能对小数取余,而pow函数返回double类型
补充
CSP-J快速幂函数完全指南
1. 为什么需要快速幂?
问题背景:计算
2^50或3^1000000时,暴力连乘会超时且溢出。暴力法缺陷:
// 计算a^n,循环n次,O(n)复杂度 long long pow_slow(long long a, long long n) { long long res = 1; for (int i = 0; i < n; i++) res *= a; // n=10^9时,循环10^9次,必超时! return res; }CSP-J数据范围:
n ≤ 10^9,暴力法完全不可行。
2. 快速幂核心思想:二进制拆分
数学原理:利用幂的乘方性质,将指数
n按二进制拆分。a^13 = a^(1101)₂ = a^(8) × a^(4) × a^(1)关键观察:
每次将指数折半,底数平方
只乘当指数二进制位为1时的底数
时间复杂度:**O(log n) **,计算
a^10^9仅需30次循环!
** 3. 迭代实现(CSP-J首选)**
#include <bits/stdc++.h> using namespace std; // 快速幂模板:计算 a^n % mod long long qpow(long long a, long long n, long long mod) { long long res = 1; // 结果初始化为1 a %= mod; // 防止底数过大 while (n) { // 当指数不为0 if (n & 1) { // 如果n的二进制末位是1(奇数) res = res * a % mod; // 乘到结果中 } a = a * a % mod; // 底数平方 n >>= 1; // 指数右移一位(折半) } return res; } // 示例:计算 2^10 mod 1000000007 int main() { long long ans = qpow(2, 10, 1e9+7); // ans = 1024 cout << ans << endl; // 输出1024 return 0; }代码解析:
n & 1:判断指数奇偶性(等价于n % 2 == 1)
n >>= 1:指数折半(等价于n /= 2)
a = a * a % mod:底数平方并取模,防止溢出
4. 递归实现(易懂但稍慢)
long long qpow(long long a, long long n, long long mod) { if (n == 0) return 1; // 边界:a^0 = 1 long long half = qpow(a, n / 2, mod); // 递归计算a^(n/2) half = half * half % mod; // 平方 if (n & 1) half = half * a % mod; // 如果n是奇数,多乘一个a return half; }CSP-J建议:用迭代,递归深度log n可能栈溢出(n=10^9时深度约30,安全但迭代更快)。
5. 复杂度分析
方法 时间复杂度 循环次数(n=10^9) CSP-J适用性 暴力连乘 O(n) 10^9次 ❌ 必超时 快速幂 O(log n) 30次 ✅ 完美 空间复杂度:O(1),只使用常数变量。
6. CSP-J典型应用场景
场景1:大数幂取模(最常见)
// 题目:计算 a^b mod 1337 (a,b ≤ 10^9) long long ans = qpow(a, b, 1337);场景2:斐波那契数列(矩阵快速幂入门)
// 求F(n) mod 1e9+7,n ≤ 10^18 // 用矩阵快速幂:[[1,1],[1,0]]^n = [[F(n+1),F(n)],[F(n),F(n-1)]] // CSP-S内容,J组只需知道快速幂可扩展到矩阵场景3:模逆元
// 求a在模p下的逆元(a与p互质) // a^(-1) ≡ a^(p-2) (mod p) (费马小定理) long long inv = qpow(a, mod-2, mod); // mod是质数
7. 注意事项与竞赛陷阱
陷阱1:不取模导致溢出
// ❌ 错误:中间乘法可能溢出long long res = res * a; // res和a都可能接近1e9,乘积可达1e18,long long最大9e18,风险! // ✅ 正确:每次乘法后立即取模 res = res * a % mod; a = a * a % mod;陷阱2:mod=1的特殊情况
qpow(a, n, 1); // 任何数mod 1都是0,直接返回0陷阱3:底数为0且指数为0
// 0^0数学上无定义,通常返回1 if (a == 0 && n == 0) return 1; // 根据题目要求处理
8. CSP-J标准模板(直接背诵)
// 万能快速幂模板(支持mod=1的情况) long long qpow(long long a, long long n, long long mod) { if (mod == 1) return 0; // 任何数mod 1都是0 long long res = 1; a %= mod; while (n) { if (n & 1) res = (res * a) % mod; a = (a * a) % mod; n >>= 1; } return res; } // 快速乘(防止乘法溢出,当mod接近1e18时使用) // 原理:a*b % mod = (a*b - (long long)((long double)a*b/mod)*mod + mod) % mod long long qmul(long long a, long long b, long long mod) { a %= mod; b %= mod; long long res = 0; while (b) { if (b & 1) res = (res + a) % mod; a = (a + a) % mod; b >>= 1; } return res; }
9. 如何快速验证你的快速幂?
测试用例:
// 测试1:基本功能 qpow(2, 10, 1000) == 1024 % 1000 == 24 // 测试2:大指数 qpow(2, 1000000000, 1000000007) // 结果在合理范围 // 测试3:mod=1 qpow(123, 456, 1) == 0 // 测试4:指数为0 qpow(100, 0, 1000) == 1 // 测试5:底数为0 qpow(0, 10, 1000) == 0
10. 快速幂vs pow函数
#include <cmath> // ❌ pow函数问题多 double res = pow(2, 100); // 1. 结果为double,有精度误差 // 2. 无取模功能 // 3. 速度慢10倍 // ✅ 快速幂优势 long long res = qpow(2, 100, mod); // 1. 精确整数 // 2. 支持取模 // 3. O(log n)速度竞赛建议:永远不要在大数运算中使用
pow(),一律用快速幂。
11. 核心要点总结(背诵版)
目的:解决大指数幂运算的超时和溢出问题
核心:二进制拆分,
a^n = a^(n/2) × a^(n/2) × (a 若n为奇数)模板:迭代版比递归版快,务必背熟
三要素:
res=1,while(n),n&1判断防溢出:每次乘法后立即
% mod,不能用pow()复杂度:时间O(log n),空间O(1),循环次数≈30次(当n=10^9)
应用:大数幂取模、模逆元、矩阵快速幂(进阶)
竞赛箴言:遇到
a^b mod p且b>10^5,直接上快速幂模板,这是CSP-J选手的基本素养。
1414

被折叠的 条评论
为什么被折叠?



