2021杭电多校第一场

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值