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

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

Codeforces Round #841 (Div. 2) and Divide by Zero 2022

Codeforces Round #841 (Div. 2) and Divide by Zero 2022

o(╥﹏╥)o

2022的最后一场也没打好

B题反正我是理解错了,我看到题目上写着要相乘再取模,结果就真的去先乘再取模,这样想都不用想会爆,真无语,反正B没写好我后面的也不想看了,C题也没怎么看就直接看答案了(不过要是我看了也不会想到那么巧妙的解题方法的)

B

B

还有一点我没有做出来的一点是,我推出了答案是

i=1ni2 +i=1n1i(i+1)

而我就好像只知道第一个怎么推导,后面一个我竟然用循环求答案(现在想起就无语,这真的是我吗)

然后我换了一种策略,我发现题目给的案列的答案最后一个不能被2022整除,于是我就异想天开,以为后面的答案都是同一个数(我脑子呢,后面还要取余呀)

以上是我的愚蠢行为

2i=1ni2 +i=1nin(n1)

后面我发现上面那一个公式可以推导为

这样就很好算了(括号是个很麻烦的东西,但需要求累和的时候,尽量把括号解决)

还有,在求这个答案的时候可以取余的哦,不要被题目后面的话误导了

还有一个问题是我在求这一个答案中和队友们想明白的问题

就是在一个既有取余,又有除法的求值过程中,如果直接按照乘法的那种直接取余

6%4/3和6/3%4答案是不同的,取余后和取余前除出来的数不同

我想起以前看到一些大佬求除法都是以逆元的形式,以前想不明白,现在想起觉得任何事都有它的理由,现在可能不知道,到后面你有可能就会明白了,这种感觉太妙了

#include <iostream>
using namespace std;
#define int long long 
const int mod=1e9+7;
int n,t;
int two,three;
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 fun(int n)
{
    int ans=n*(n+1)%mod*(2*n+1)%mod*three%mod;
    ans=(ans-(n*(n+1)%mod*two%mod));
    ans=(ans%mod+mod)%mod;
    ans=(ans*2022)%mod;
    return ans;
}
void solve()
{
    cin>>n;
    cout<<fun(n)<<'\n';
    return ;
}
signed main ()
{
    cin>>t;
    two=ksm(2,mod-2);
    three=ksm(3,mod-2);
    while (t--)
    {
        solve();
    }
    system ("pause");
    return 0;
}

C

C

这道题我感觉妙不可言的地方就在它运用了正难则反的思想

还用到了“前缀和”来求一段的异或值

其他的看代码感受

#include <iostream>
#include <map>
#include <vector>
using namespace std;
const int maxn=2e5+10;
#define int long long 
int n,t;
void solve()
{
    cin>>n;
    vector<int> a(n+1), cnt(2 * n+2);//cnt[i],数字i出现的次数
    cnt[0]++;//从1开始的
    long long  ans=n*(n+1)/2;//一共有这么多种,下面我们通过寻找不符合条件的来求出最后所有符合条件的,
    int pp=0;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i];
        a[i]=a[i-1]^a[i];//a[i]代表从1到i的异或值,异或的前缀和
        for (int j=0;j*j<=2*n;j++)
        {
            int now=j*j;//平方数一定只有奇数个因子
            int p=now^a[i];//p^a[i]==now,p也是一个前缀和,而且是在a[i]前面的,假如p是a[k],那么这一段就是K+1到i这一段的异或值是now
            if (p>2*n) break;
            pp+=cnt[p];//我们要减去不符合条件的(cnt是p出现过的)
        }
        cnt[a[i]]++;//此时a[i]出现过一次
    }
    cout<<ans-pp<<'\n';
    return ;
}
signed  main ()
{
    ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
    cin>>t;
    while (t--)
    {
        solve();
    }
    system ("pause");
    return 0;
}

还有一个气愤的是我cnt用 map存就超时了,后来查了一下,map的查询是O(logn),而数组是O(1)

D

D

这一道题的存数组的大小不好控制,我这里用了二维vector

然后但一个l是满足条件的时候,比l小的一定是满足条件的,由此,这一道题可以用二分来做

而且,这一道题还用到了二维前缀和,来判断这一个区域是不是都>l

#include <iostream>
#include <stdlib.h>
#include <vector>
using namespace std;
int n,t,m;
bool check(int x,vector<vector<int>>c)
{
    vector<vector<int>>b(n+1,vector<int>(m+1));
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=m;j++)
        {
            int now=0;
            if (c[i][j]>=x) now=1;
            b[i][j]=b[i-1][j]+b[i][j-1]-b[i-1][j-1]+now;
        }
    }
    for (int i=x;i<=n;i++)
    {
        for (int j=x;j<=m;j++)
        {
            int now=b[i][j]-b[i][j-x]-b[i-x][j]+b[i-x][j-x];
            if (now==x*x) return true;
        }
    }
    return false;
}
void solve()
{
    cin>>n>>m;
    vector<vector<int>>a(n+1,vector<int>(m+1));
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=m;j++)
        {
            cin>>a[i][j];
        }
    }
    int l=1,r=min(n,m)+1;
    int ans=-1,mid;
    while (l<=r)
    {
        mid=(l+r)>>1;
        if (check(mid,a))
        {
            l=mid+1;
            ans=mid;
        }
        else r=mid-1;
    }
    cout<<ans<<'\n';
    return ;
}
int main ()
{
    cin>>t;
    while (t--)
    {
        solve();
    }
    system ("pause");
    return 0;
}
posted @   righting  阅读(83)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示