每一年都奔走在自己热爱里

没有人是一座孤岛,总有谁爱着你

AtCoder Beginner Contest 298(D,F)

AtCoder Beginner Contest 298(D,F)

D(思维,模拟,快速幂)

D

大意是最初有一个数字\(1\),然后进行\(q\)个操作

有三种操作

\(1\),输入\(1,x\),在原来的数字后面添加一个尾数,例如原本的数是\(12\),输入了\(1 5\),数字变成了\(125\)

\(2\),输入\(2\),把原来的数字第一位数删除,例如原本的数是\(125\),输入了\(2\),数字变成了\(12\)

\(3\),输入\(3\),我们需要输出此时的数字(对一个数取模)

一开始我想的比较复杂

其实对于添加,我们只需乘\(10\)\(x\)

对于删除,我们只需要让此时的数字减去此时的数的首位乘上\(10^{len}\),所以,我们需要记录首位数(可以用队列),还有长度

但是,这里要注意一下,就是相减

正确的处理如下

//a-=b,%mod
a=((a-b)%mod+mod)%mod;
//而不是 a=(a-b+mod)%mod,有可能这个b非常大,加了mod后还是负数,不能把最后的答案变成正数
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include<cmath>
#include <unordered_map>
#include <array>
#include <cstring>
using namespace std;
#define int long long 
#define LL long long
#define ios  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define inf 1e18
#define INF 1e18
#define mem(a,b) memset((a),(b),sizeof(a))
const int maxn=6e5+10;
const int mod=998244353;
int n,q;
int ans=1;
int len=0;
int l=1;
queue<int>qq;
int ksm(int x,int p)
{
    int res=1;
    while (p)
    {
        if(p&1)
        {
            res=res*x%mod;
        }
        x=x*x%mod;
        p>>=1;
    }
    return res;
}
int inv(int x)
{
    return ksm(x,mod-2);
}
signed main ()
{
    cin>>q;
    qq.push(1);
    while (q--)
    {
        int op;
        cin>>op;
        if(op==1)
        {
            int x;
            cin>>x;
            qq.push(x);
            ans=(ans*10ll+x)%mod;
            len++;
        }
        else if(op==2)
        {
            int top=qq.front();
            qq.pop();
            int p=(top*ksm(10,len)%mod)%mod;
            ans=((ans-p)%mod+mod)%mod;
              len --;
        }
        else if(op==3)
        {
             cout<<ans<<"\n";
        }
    }
    system ("pause");
    return 0;
}

这次我的\(e\)过了,很简单的一个概率\(dp\),这里就不写了

F(set,思维)

F

题目大意是有一个很大的网格,只有其中的\(n\)个位置有数在这些位置上,其他的都是\(0\)

我们选择一对\(x,y\),\(x\)行和\(y\)列的这个十字架上面的所有位置的和,求这个和的最大值

我们先预先处理好行的和\(sumx\)和列的和\(sumy\)

有两种情况

\(x,y\)上面有数据,那么此时的和就是\(sumx[x]+sumy[y]-a[x] [y]\)(两个都加了一次,这个位置加了两次)

\(x,y\)上面没有数据,直接相加

对于\(x,y\)上面没有数据,我们可以枚举每一个出现过数据的行,然后再在后面的那些没有和这一个行有关系的列中选择,由于不用减,故直接选择较大的那一个,(对于可以很容易删除,可以很容易得到最大值的那一个,我们可以想到\(set\)),后来还有记得把原来删除的列的数据加回来,比较每一个行所相关联的列都是不一样的)

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include<cmath>
#include <unordered_map>
#include <array>
#include <cstring>
using namespace std;
#define int long long 
#define LL long long
#define ios  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define inf 1e18
#define INF 1e18
#define mem(a,b) memset((a),(b),sizeof(a))
const int maxn=6e5+10;
const int mod=998244353;
int n;
struct node
{
    int x,y,val;
}a[maxn];
map<int,int>sumx,sumy;
set<pair<int,int>>py,px;
map<int,vector<int>>pei;
signed main ()
{
    cin>>n;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i].x>>a[i].y>>a[i].val;
        sumx[a[i].x]+=a[i].val;
        sumy[a[i].y]+=a[i].val;
        pei[a[i].x].push_back(a[i].y);
    }
    int ans=0;
    for (int i=1;i<=n;i++)
    {
        int now=sumx[a[i].x]+sumy[a[i].y]-a[i].val;
        ans=max(ans,now);
    }
    for (auto [y,sum]:sumy)
    {
        py.insert({sum,y});
    }
    for (auto [x,sum]:sumx)
    {
        px.insert({sum,x});
    }
    for (auto [sum,x]:px)
    {
        for (auto y:pei[x])//和x行相关联的y
        {
            py.erase({sumy[y],y});
        }
        if(py.size())
        {
            int now=sum+(*(--py.end())).first;
            ans=max(ans,now);
        }
        for (auto y:pei[x])
        {
            py.insert({sumy[y],y});
        }
    }
    cout<<ans<<"\n";
    system ("pause");
    return 0;
}
posted @ 2023-05-27 17:01  righting  阅读(22)  评论(0)    收藏  举报