QBXT游记 | Day1 Moring
高精度
就是压位+重载运算符
我们知道如果直接进行加法的话,复杂度\(O(n)\)的,所以我们压位就可以把这个\(n\)变小,从而缩减时间
下面直接贴题目,是洛谷的P1005,P1005使用到了高精度+高精度,高精度*常数以及高精度-高精度
实际上重载了运算符之后和之前放在主函数里面的写法是基本上一样的,只不过用起来更加方便而已
#include <bits/stdc++.h>
#define Heriko return
#define Deltana 0
#define S signed
#define U unsigned
#define LL long long
#define R register
#define I inline
#define D double
#define LD long double
#define mst(a,b) memset(a,b,sizeof(a))
#define ON std::ios::sync_with_stdio(false)
using namespace std;
I void fr(LL &x)
{
LL f=1;char c=getchar();
x=0;
while(c<'0'||c>'9')
{
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
x*=f;
}
const int M=10000;
LL n,m,a[90];
struct Bint
{
LL p[555],len;
Bint()
{
mst(p,0);
len=0;
}
void pr()
{
printf("%lld",p[len]);
for(R LL i=len-1;i>=1;i--)
{
if(p[i]==0)
{
printf("0000");
continue;
}
for(R LL j=10;j*p[i]<M;j*=10) printf("0");
printf("%lld",p[i]);
}
}
}f[90][90],b[90],ans,k;
Bint operator+(const Bint &a,const Bint &b)
{
Bint c;c.len=max(a.len,b.len);
LL r=0;
for(R LL i=1;i<=c.len;i++)
{
c.p[i]=a.p[i]+b.p[i]+r;
r=c.p[i]/M;
c.p[i]%=M;
}
if(r>0) c.p[++c.len]=r;
Heriko c;
}
Bint operator*(const Bint &a,const int &b)
{
Bint c;c.len=a.len;
LL r=0;
for(R LL i=1;i<=c.len;i++)
{
c.p[i]=a.p[i]*b+r;
r=c.p[i]/M;
c.p[i]%=M;
}
while(r>0) c.p[++c.len]=r%M,r/=M;
Heriko c;
}
Bint Bmax(const Bint &a,const Bint &b)
{
if(a.len>b.len) Heriko a;
else if(a.len<b.len) Heriko b;
for(R LL i=a.len;i>=1;i--)
if(a.p[i]>b.p[i]) Heriko a;
else if(a.p[i]<b.p[i]) Heriko b;
Heriko a;
}
S main()
{
fr(n),fr(m);
b[0].p[1]=1,b[0].len=1;
for(R LL i=1;i<=m+2;i++) b[i]=b[i-1]+b[i-1];
while(n--)
{
mst(f,0);
for(R LL i=1;i<=m;i++) fr(a[i]);
for(R LL i=1;i<=m;i++)
for (R LL j=m;j>=i;j--) {
f[i][j]=Bmax(f[i][j],f[i-1][j]+b[m-j+i-1]*a[i-1]);
f[i][j]=Bmax(f[i][j],f[i][j+1]+b[m-j+i-1]*a[j+1]);
}
k=Bint();
for(R LL i=1;i<=m;i++) k=Bmax(k,f[i][i]+b[m]*a[i]);
ans=ans+k;
}
ans.pr();
Heriko Deltana;
}
我写完了.jpg
😂
其实今天还是说了一些小的点
sscanf(s+j,"%d",&k);
的意思是指从字符串中的第0
到j - 1
位赋值到k中printf("%09d",k);
是指在输出k的时候如果不满9位就用0来补齐,也就是说会加上前导0
上课老师使用了另外一种写法,和上面我之前写的有一些地方不一样,在这里就简单的贴一些结构体和乘法
struct Bint
{
LL p[114514],len;
Bint()
{
mst(p,0);
len=0;
}
void br()
{
cin>>s;
LL ln=strlen(s);
len=(ln-1)/4;
for(R LL i=0,j=ln-4;i<=len;i++,j-=4)
{
/*
solution 1:
LL ans=0;
for(R LL k=0;k<9;k++) ans=ans*10+s[j+k]-'0';
p[i]=ans;
*/
//solution 2:
sscanf(s+j,"%lld",&p[i]);//这里的sscanf是从一个字符串读入
s[j]='\0';
/*
solution 3:
atoi函数
*/
}
sscanf(s,"%lld",&p[i]);
}
void pr()
{
printf("%lld",p[len]);
for(R LL i=len-1;i>=0;i--) printf("%04lld",p[i]); //不够9位用0补全
}
};
Bint operator * (const Bint &a,const Bint &b)
{
Bint c;c.len=a.len+b.len+1;
for(R LL i=0;i<=a.len;i++)
for(R LL i=j=0;j<=b;j++)
{
c.p[i+j]+=a.p[i]*b.z[j];
c.p[i+j+1]+=c.p[i+j]/M;
c.p[i+j]=c.p[i+j]%M;
}
for(R LL i=0;i<=c.len;i++) if(c.z[i]>=M) c.z[i+1]++,c.z[i]-=M;
while(c.len>0 && !c.z[c.len]) c.len--;
Heriko c;
}
上面的\(solution\ 3\)中说到了atoi
这个函数
于是下面来稍微说一下
int k;char s[5]={"114514"};
k=stoi(s);
要注意的是这里返回的是一个int,所以超过int范围的好像不能转换
不过在高精度压位这里int肯定够了
其他
实际上本来是不想记录其他的内容的,因为太水了,但是还是记录一下吧
同余
实际上同余的性质大家都知道,在这里就简单的写一下
\((a±b)\mod m=(a\mod m ± b\mod m)\mod m\)
\(ab\mod m=(a \mod m\ \cdot\ b \mod m )\mod m\)
C++ feature
进行取余运算的时候,结果(也就是带余除法中的余数)和被除数同号
也就是说,5%=2
的结果是2
,而-5%2
的结果是-2
GCD & LCM
实际上之前有记录过,朴素的实现方法很简单
int gcd(int x,int y)
{
return !y ? a : gcd(y,x%y);
}
int lcm(int x,int y)
{
return (x*y)/gcd(x,y);
}
至于高级的方法,今天没讲🙂
Do you like WHAT YOU SEE ?