蓝桥杯越来越近,煮波复习的毫无头绪(其实还是因为煮波只会用纯暴力的方法解题),所以煮波就整理了一些之前训练的时候的一些比较常用的模板:
1-快速幂
之前的文章中讲过,为了方便煮波就把他们整理到一块了
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
int fast_power(int a,int b,int c)//a的b次方对c取余
{
a%=c;//防止a过大,先对a取余
int ans=1;
while(b)
{
if(b&1)//b%2==1
{
ans=(ans*a)%c;//乘一次取余一次(取余的性质)
}
a=(a*a)%c;//同理
b/=2;
}
return ans;
}
signed main()
{
int a,b,c;
cout<<fast_power(a,b,c)<<endl;
return 0;
}
这个是最基础的a的b次方对c取模的快速幂的模板,相应的取模运算煮波也整理了一些技巧
1)对于加法运算和乘法运算 取模不会对结果造成影响[eg.(a+b)%c==(a%c+b%c)%c],乘法也是一样的。
2)对于减法,由于可能出现负数,所以公式会有一点改变[(a-b)%c==(a%c-b%c+c)%c],不要问为什么这样变,手写几个就出来了(蓝桥杯马上就开始了,煮波也是为了方便才这样记的)
3)对于除法,我们可以把它看成乘法来算,对于一个素数来说,除以一个数等于乘以他的乘法逆元(只需要记住a的乘法逆元是a的m-2次方),eg[(a/b)%c==(a%c*b^c-2)%c](当a和b互质时才成立,但是基础题一般不会出不互质的情况)
2-高精度(煮波是C/C++组的,高精度需要自己手搓)
1)高精度加法
洛谷题目来源:高精度加法
#include <stdio.h>
#include <string.h>
#define N 100010
char s1[N], s2[N];
int a[N], b[N], c[N];
int main() {
scanf("%s%s", s1, s2);
int len1 = strlen(s1);
int len2 = strlen(s2);
for (int i = len1-1; i >= 0; i--) {
a[len1 - i] = s1[i] - '0';
}
for (int i = len2-1; i >= 0; i--) {
b[len2 - i] = s2[i] - '0';
}
int len = (len1 > len2) ? len1 : len2;
//printf("%d", len);
int num = 0;
for (int i = 1; i <= len; i++) {
int sum = a[i] + b[i] + num;
c[i] = sum % 10;
num = sum / 10;
}
if (num > 0) {
len++;
c[len] = num;
}
for (int i = len; i >= 1; i--) {
printf("%d", c[i]);
}
return 0;
}
2)高精度减法:
洛谷题目来源:高精度减法
#include <stdio.h>
#include <string.h>
#define N 10010
char s1[N],s2[N],temp[N];
int a[N],b[N],c[N];
int main()
{
int sign=0;
scanf("%s%s",s1,s2);
int lena=strlen(s1);
int lenb=strlen(s2);
//sign=(lena>lenb)?0:1;
if(lena<lenb||lena==lenb&&strcmp(s1,s2)<0)
{
sign=1;
strcpy(temp,s1);
strcpy(s1,s2);
strcpy(s2,temp);
int t=lena;
lena=lenb;
lenb=t;
}
//int len=(lena>lenb)?lena:lenb;
for(int i=1;i<=lena;i++)
a[i]=s1[lena-i]-'0';
for(int i=1;i<=lenb;i++)
b[i]=s2[lenb-i]-'0';
for(int i=1;i<=lena;i++)
{
if(a[i]<b[i])
{
a[i+1]--;
a[i]+=10;
}
c[i]=a[i]-b[i];
}
while(c[lena]==0&&lena>1)
lena--;
if(sign==1)
printf("-");
for(int i=lena;i>=1;i--)
printf("%d",c[i]);
return 0;
}
3)高精度乘法
洛谷题目来源:高精度乘法
#include <stdio.h>
#include <string.h>
#define N 10000010
char s1[N],s2[N];
int a[N],b[N],c[N];
int main()
{
scanf("%s%s",s1,s2);
int len1=strlen(s1),len2=strlen(s2);
for(int i=len1-1,j=0;i>=0;i--,j++)
a[j]=s1[i]-'0';
for(int i=len2-1,j=0;i>=0;i--,j++)
b[j]=s2[i]-'0';
int len=len1*len2;
for(int i=0;i<len1;i++)
{
for(int j=0;j<len2;j++)
{
c[i+j]+=a[i]*b[j];
c[i+j+1]+=c[i+j]/10;
c[i+j]%=10;
}
}
while(c[len]==0&&len>0)len--;
for(int i=len;i>=0;i--)
printf("%d",c[i]);
return 0;
}
4)高精度除法
洛谷题目链接:高精度除法
#include <stdio.h>
#include <string.h>
#define N 1000010
char s1[N],c[N];
int a[N];
int main()
{
scanf("%s",s1);
long long b;
scanf("%lld",&b);
if(s1[0]=='0')
{
printf("0");
return 0;
}
int len=strlen(s1);
for(int i=0;i<len;i++)
{
a[i]=s1[i]-'0';
}
long long r=0;
for(int i=0;i<len;i++)
{
c[i]=(r*10+a[i])/b;
r=(r*10+a[i])%b;
}
int low=0;
while(c[low]==0&&low<len-1)
low++;
for(int i=low;i<len;i++)
printf("%d",c[i]);
return 0;
}
5)融合升级版
#include <bits/stdc++.h>
using namespace std;
int s[100],a[100];
void multi(int k)
{
int loss=0;
for(int i=99;i>=0;i--)
{
a[i]=a[i]*k+loss;
loss=a[i]/10;
a[i]%=10;
}
}
void add()
{
int loss=0;
for(int i=99;i>=0;i--)
{
s[i]+=a[i]+loss;
loss=s[i]/10;
s[i]%=10;
}
}
int main()
{
int n;
cin>>n;
a[99]=1;
for(int i=1;i<=n;i++)
{
multi(i);
add();
}
int low=0;
while(low<99&&s[low]==0)
{
low++;
}
for(int i=low;i<=99;i++)
{
cout<<s[i];
}
return 0;
}
3-素数筛法
线性筛(欧拉筛)
#include <bits/stdc++.h>
using namespace std;
#define N 100000005
int a[N];
long long b[N];
int main()
{
long long n,q;
int t,ant=0;
scanf("%lld %lld",&n,&q);
for(long long i=2;i<=n;i++)
{
if(a[i]==0)
b[++ant]=i;
for(long long j=1;j<=ant;j++)
{
if(i*b[j]>n) break;
a[b[j]*i]=1;
if(i%b[j]==0) break;
}
}
while(q--)
{
scanf("%d",&t);
printf("%lld\n",b[t]);
}
return 0;
}
埃氏筛
#include <stdio.h>
int pri[10005];
int main()
{
//埃氏筛
for(int i=2;i<=10000;i++)
{
if(pri[i]==0)
{
for(int j=i*i;j<=10000;j+=i)
{
pri[j]=1;
}
}
}
int n,ans=0;
while(~scanf("%d",&n))
{
ans=0;
for(int i=2;i<=n/3;i++)
{
for(int j=i;j<=(n-i)/2;j++)
{
if(!pri[i]&&!pri[j]&&!pri[n-i-j]) ans++;
}
}
printf("%d\n",ans);
}
return 0;
}
时间关系,煮波等在以后更加深入的算法学习中会总结更多的模板并且会更新到这个文章中,想要用最少时间得到更多基础模板的小伙伴可以收藏,煮波会持续更新