题面:
题意:
给定一个nm的矩阵,其中aij = lcm( i , j )。
求所有大小为kk的子矩阵的最大值的和。
官方题解:
不过我的lcm是,n*m log n 求的。。。
还好没T。
代码:
①、
2304ms
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
#define len(x) (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e18;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1.0);
const int hp=13331;
const int maxn=5100;
const int maxm=100100;
const int up=100000;
int a[maxn][maxn],b[maxn][maxn];
int c[maxn],q[maxn];
int gcd(int a,int b)
{
if(a==0||b==0) return a|b;
return gcd(b,a%b);
}
int lcm(int a,int b)
{
return a/gcd(a,b)*b;
}
int main(void)
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
a[i][j]=lcm(i,j);
}
for(int i=1;i<=m;i++)
{
int l=1,r=0;
for(int j=1;j<=n;j++)
{
while(l<=r&&q[l]<=j-k) l++;
while(l<=r&&a[q[r]][i]<=a[j][i]) r--;
q[++r]=j;
b[j][i]=a[q[l]][i];
}
}
ll ans=0;
for(int i=1;i<=n;i++)
{
int l=1,r=0;
for(int j=1;j<=m;j++)
{
while(l<=r&&q[l]<=j-k) l++;
while(l<=r&&b[i][q[r]]<=b[i][j]) r--;
q[++r]=j;
if(i>=k&&j>=k)ans=ans+b[i][q[l]];
}
}
printf("%lld\n",ans);
return 0;
}
②、
开三个数组就会MLT。
888ms
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
#define len(x) (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e18;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1.0);
const int hp=13331;
const int maxn=5100;
const int maxm=100100;
const int up=100000;
int a[maxn][maxn],b[maxn][maxn];
int c[maxn],q[maxn];
int main(void)
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(!b[i][j])//i,j互质
{
for(int k=1;k*i<=n&&k*j<=m;k++)
b[k*i][k*j]=k,a[k*i][k*j]=i*j*k;
}
}
}
for(int i=1;i<=m;i++)
{
int l=1,r=0;
for(int j=1;j<=n;j++)
{
while(l<=r&&q[l]<=j-k) l++;
while(l<=r&&a[q[r]][i]<=a[j][i]) r--;
q[++r]=j;
b[j][i]=a[q[l]][i];
}
}
ll ans=0;
for(int i=1;i<=n;i++)
{
int l=1,r=0;
for(int j=1;j<=m;j++)
{
while(l<=r&&q[l]<=j-k) l++;
while(l<=r&&b[i][q[r]]<=b[i][j]) r--;
q[++r]=j;
if(i>=k&&j>=k)ans=ans+b[i][q[l]];
}
}
printf("%lld\n",ans);
return 0;
}
③、O(值域预处理),O(1)查询的gcd
1292ms
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
#define len(x) (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e18;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1.0);
const int hp=13331;
const int maxn=5100;
const int maxm=100100;
const int up=100000;
int prime[maxn],fac[maxn][3],gcd[110][110],cnt=0;
bool ha[maxn];
int a[maxn][maxn],b[maxn][maxn];
int c[maxn],q[maxn];
int ppt;
void Prime(int n)
{
ppt=sqrt(n)+1;
fac[1][0]=fac[1][1]=fac[1][2]=1;
ha[1]=true;
for(int i=2;i<=n;i++)
{
if(!ha[i])
{
prime[cnt++]=i;
fac[i][0]=fac[i][1]=1;
fac[i][2]=i;
}
for(int j=0;j<cnt&&i*prime[j]<=n;j++)
{
int now=i*prime[j];
ha[now]=true;
fac[now][0]=fac[i][0]*prime[j];
fac[now][1]=fac[i][1];
fac[now][2]=fac[i][2];
if(fac[now][0]>fac[now][1]) swap(fac[now][0],fac[now][1]);
if(fac[now][1]>fac[now][2]) swap(fac[now][1],fac[now][2]);
if(i%prime[j]==0) break;
}
}
for(int i=0;i<=ppt;i++) gcd[i][0]=gcd[0][i]=i;
for(int i=1;i<=ppt;i++)
for(int j=1;j<=i;j++)
gcd[i][j]=gcd[j][i]=gcd[j][i%j];
}
int gg(int a,int b)
{
int ans=1;
for(int i=0;i<=2;i++)
{
int now=0;
if(fac[a][i]>ppt)
{
if(b%fac[a][i]==0) now=fac[a][i];
else now=1;
}
else now=gcd[fac[a][i]][b%fac[a][i]];
b/=now;
ans*=now;
}
return ans;
}
int main(void)
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
Prime(max(n,m));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
a[i][j]=i*j/gg(i,j);
}
}
for(int i=1;i<=m;i++)
{
int l=1,r=0;
for(int j=1;j<=n;j++)
{
while(l<=r&&q[l]<=j-k) l++;
while(l<=r&&a[q[r]][i]<=a[j][i]) r--;
q[++r]=j;
b[j][i]=a[q[l]][i];
}
}
ll ans=0;
for(int i=1;i<=n;i++)
{
int l=1,r=0;
for(int j=1;j<=m;j++)
{
while(l<=r&&q[l]<=j-k) l++;
while(l<=r&&b[i][q[r]]<=b[i][j]) r--;
q[++r]=j;
if(i>=k&&j>=k)ans=ans+b[i][q[l]];
}
}
printf("%lld\n",ans);
return 0;
}