2021杭电多校第一场补题
1001 Mod, Or and Everything
思路
题目比较简单,可以先打表发现规律,然后再根据规律写代码,代码也不复杂。
附上代码
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int n;
ll k;
cin>>n;
while(n--)
{
cin>>k;
if(k<=2)
{
cout<<"0"<<endl;
}
else
{
ll i=1;
for(i=1;k>(i<<1);i=(i<<1));//对int型数据左移相当于乘2
cout<<i-1<<endl;
}
}
return 0;
}
1005 Minimum spanning tree
思路
根据题意点是从2到n的。
因此对于每一个点i来说,如果i是质数,那么就让该质数和最小的点2相乘作为边;如果i是合数,则i一定存在一个因数,就让其与该因数连接,那么这条边就是i。这样累加起来就是最后的答案了。
附上代码
#include<bits/stdc++.h>
using namespace std;
int prime[5000000];
bool noprime[10000010];
long long f[10000010];
void init()
{
memset(noprime,false,sizeof(noprime));
int sk=0;
for (int i=2; i<=10000000; i++)
{
if (!noprime[i]) prime[++sk]=i;
for (int j=1; j<=sk&&i*prime[j]<=10000000; j++)
{
noprime[i*prime[j]]=1;
if (i%prime[j]==0) break;
}
}
}
int main()
{
init();
f[2]=0;
for (int i=3; i<=10000000; i++)
if(noprime[i])
f[i]=f[i-1]+i;
else f[i]=f[i-1]+2*i;
int t;
scanf("%d",&t);
while (t)
{
t--;
int n;
scanf("%d",&n);
printf("%lld\n",f[n]);
}
}
1006 Xor sum
待补
1008 Maximal submatrix
思路
首先是对矩阵进行第一次的处理,定义二维数组h,h[i][j]表示再矩阵m[i][j]这一列上到j这一点的非降序序列的长度。例如某一列的值为1,2,3,4,5,8,7,9,那么我们就可以得出h数组中同一列的值为1,2,3,4,5,6,1,2。
其次进行第二步的处理,就是总共的n行矩阵,对于每一行进行单调栈的弹入弹出操作,从而找到每一个点能得到的最大子矩阵的元素个数。我们可以知道这个循环需要循环n次,循环之后得到的最大值就是最后的答案。
附上代码
#include <bits/stdc++.h>
using namespace std;
int Matrix[2121][2121],area[2121],h[2121][2121];
int main()
{
int n,m,T;
scanf("%d",&T);
while(T--)
{
int ans=0;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
{
scanf("%d",&Matrix[i][j]);
if(i==1||Matrix[i][j]<Matrix[i-1][j])
h[i][j]=1;
else
h[i][j]=h[i-1][j]+1;//对于该点求得长度
}
for(int k=1; k<=n; k++) //单调栈处理该题,总共循环n次,因为矩阵总共有n行
{
stack<int>S;
int maxx=0,i=1;
//每次插入时,计算出的是左边比待插入值大的个数,(比待插入值大的数)在自己位置右边比自己大的数
while(i<=m)
{
if(S.empty()||h[k][i]>=S.top()) //录入
{
S.push(h[k][i++]);
area[S.size()]=1;//area实际上是记录连续的可组成点的个数的
}
else //遇到小于栈顶的值进行面积统计
{
int line=0;//用来统计行
while(!S.empty()&&S.top()>h[k][i])
{
line+=area[S.size()];//累积以当前值为基准,能够构成的左+右的连续矩阵宽度
maxx=max(maxx,S.top()*line);//计算以当前栈顶为基准能够得到的面积值
S.pop();
}
S.push(h[k][i++]);
area[S.size()]=line+1;//记录以当前值为基准,能够构成连续的左边矩阵的宽度
}
}
int line=0;
while(!S.empty()) //防止一直上升,对栈非空情况进行处理
{
line+=area[S.size()];
maxx=max(maxx,S.top()*line);
S.pop();
}
ans=max(maxx,ans);
memset(area,0,sizeof(area));
}
printf("%d\n",ans);
memset(Matrix,0,sizeof(Matrix));
memset(h,0,sizeof(h));
}
return 0;
}