24暑假集训day3上午
进制转换
一个
问题简述:将
思路:先转换成
std:
#include <iostream>
#include <string>
using namespace std;
int n; //转化前为n进制
int m; //转化后为m进制
int num_10 = 0; //转化成的10进制
string num_n; //转化前的n进制
string num_m; //转化后的m进制
int main(void)
{
cin >> n;
cin >> num_n;
cin >> m;
//n进制转为10进制
int len_n = num_n.length();
for(int i = 0; i < len_n; i++)
{
num_10 *= n;
num_10 += (num_n[i] >= 'A' && num_n[i] <= 'F') ? (num_n[i] - 'A' + 10) : (num_n[i] - '0');
}
while(num_10)
{
num_m = (char)((num_10 % m >= 10) ? (num_10 % m - 10 + 'A') : (num_10 % m + '0')) + num_m;
num_10 /= m;
}
cout << num_m;
return 0;
}
高精度表示
我们可以用一个数组来表示一个高精度数。
例如数组
高精度加减法
与列竖式一样,从低位向高位依次考虑。
做加法时,如果进位,此位
做减法时,如果借位,此位
代码实现:
#include <bits/stdc++.h>
using namespace std;
char a[1005], b[1005];//a,b 两数
int c[1005], d[1005], e[1005];//c是整数形式的a d是整数>形式的b e是和
int main()
{
cin>>a>>b;
int la = strlen(a);//a的长度
int lb = strlen(b);//b的长度
//转整数:
for(int i = 1; i <= la; i++)
{
c[i] = a[i-1] - '0';
}
for(int i = 1; i <= lb; i++)
{
d[i] = b[i-1] - '0';
}
//倒序存放:
reverse(c+1, c+la+1);
reverse(d+1, d+lb+1);
int j = la;
if(j < lb) j = lb;//最大长度
//相加并判断是否进位:
for(int i = 1; i <= j; i++)
{
e[i] += c[i] + d[i];
if(e[i] >= 10)
{
e[i+1]++;
e[i] = e[i] - 10;
}
}
//如果进了一位,说明位数多了一位,j++(位数加一):
if(e[j+1] == 1){
j++;
}
//倒序输出:
for(int i=j;i>=1;i--){
cout<<e[i];
}
return 0;
}
高精度乘法
还是与列竖式类似,逐个数位相乘,最后化简。
如果是
复杂度为
代码实现:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int c[5005],d[5005],e[10010];
char a[5005],b[5005];
int main(){
scanf("%s%s",a,b);
int la=strlen(a),lb=strlen(b);
for(int i=1;i<=la;i++){
c[i]=a[i-1]-'0';
}
for(int i=1;i<=lb;i++){
d[i]=b[i-1]-'0';
}
reverse(c+1,c+la+1);
reverse(d+1,d+lb+1);
for(int i=1;i<=la;i++){
int x=0;
for(int j=1;j<=lb;j++){
e[i+j-1]=c[i]*d[j]+x+e[i+j-1];
x=e[i+j-1]/10;
e[i+j-1]%=10;
}
e[i+lb]=x;
}
int lc=la+lb;
while(e[lc]==0&&lc>1){
lc--;
}
reverse(e+1,e+lc+1);
for(int i=1;i<=lc;i++)cout<<e[i];
return 0;
}
高精度除以低精度
与竖式除法类似,从高位向低位考虑。
竖式除法每次“带下去”的那个数实际上是目前的余数,这个余数在考虑下一位时位权会
pair<vector<int>,int> div(vector<int> A, int B){
vector<int> quotient(A.size());
int remainder =0;
for(int i=A.size()-1;i>=0;i--){
quotient[i]=(A[i]+remainder*10)/ B,
remainder=(A[i]+remainder *10)%B;
while(quotient.back()== 0){
quotient.pop_back();
}
}
return {quotient,remainder};
}
高精度压位
实际上数组每个位置不仅仅可以装一个数位。
例如我们可以让
可以限制每个位置装载
问题简述:
用高精度计算出
其中 !
表示阶乘,定义为
思路:用高精度乘上低精度,每次拿出
std:
#include<iostream>
#include<cstring>
using namespace std;
int n,a[90],b[90],c[90],f[90],d=0,len_a,len_b=1,len_c=1,len_ans,m=1;
string s;
int main(){
cin>>n;
b[0]=1;
for(int i=1;i<=n;i++){
len_a=0;
int p=i;
while(p>0){
a[len_a++]=p%10;
p/=10;
}
for(int j=0;j<len_a;j++)
for(int k=0;k<=len_b;k++)
c[j+k]+=a[j]*b[k];
for(int j=0;j<len_c;j++)
if(c[j]>9) c[j+1]+=c[j]/10,c[j]%=10;
if(c[len_c]) len_c++;
len_ans=len_b,len_b=len_c,m=max(m,len_c);
for(int k=len_c-1;k>=0;k--) b[k]=c[k];
len_c=len_a+len_ans;
memset(c,0,sizeof(c));
for(int j=0;j<m;j++){
f[j]+=b[j];
if(f[j]>9) f[j+1]+=f[j]/10,f[j]%=10;
}
}
while(!f[m]&&m>0) m--;
for(int i=m;i>=0;i--) cout<<f[i];
return 0;
}
组合数学基础
加法原理:做完一件事有
乘法原理:做完一件事有
排列数
从
第一个位置有
全排列(即
考虑第
如果不选取,则需要在前
如果选取,则首先需要给
组合数
从
每一个大小为
所以有
组合数
同样考虑第
如果不选取,则需要在前
如果选取,则需要在前
思路:
用递推式
然后使用二维前缀和预处理
std:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<set>
#include<unordered_map>
#include<bitset>
#define int long long
using namespace std;
int C[20005][2005],sum[20005][2005];
signed main(){
int t,k;
cin >> t >> k;
for (int i=0;i<=2000;i++){
C[i][0] = 1;
for (int j=1;j<=i;j++)
C[i][j] =(C[i-1][j-1] + C[i-1][j])%k;
}
for (int i=1;i<=2000;i++)
for (int j=1;j<=2000;j++){
sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1];
if(C[i][j]==0&&i>j)sum[i][j]++;
}
for (int q=1;q<=t;q++){
int n,m;
cin >> n >> m;
cout<<sum[n][min(n,m)]<<"\n";
}
}
排列数与组合数的性质
这是因为左式相当于从
范德蒙德卷积公式:
左式相当于在
一些小问题
最大公约数与最小公倍数
证明:
从而可以推出
此称为欧几里得算法。
/*
int gcd(int a, int b){
if(a == 0 && b == 0){
return a + b;
}
if(a >= b){
return gcd(a % b, b);
} else {
return gcd(b % a, a);
}
}*/
int gcd(int a, int b){
return b ? gcd(b, a % b) : a;
}
int lcm(int a, int b){
return a / gcd(a, b) * b;
}
思路:
若
考虑某一个质因子
答案即为
std:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<set>
#include<unordered_map>
#include<bitset>
#define int long long
using namespace std;
const int MAXN=100005;
inline int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=x*10+ch-48;
ch=getchar();
}
return x*f;
}
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
int lcm(int x,int y){
return x/gcd(x,y)*y;
}
signed main(){
int x,y;
x=read();
y=read();
int ans=0;
if(x==y)ans--;
y*=x;
for(int i=1;i<=sqrt(y);i++){
if(y%i==0&&gcd(i,y/i)==x){
ans+=2;
}
}
cout<<ans;
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 为DeepSeek添加本地知识库
· 精选4款基于.NET开源、功能强大的通讯调试工具
· DeepSeek智能编程
· 大模型工具KTransformer的安装
· [计算机/硬件/GPU] 显卡