首页 > 其他分享 >CSP模拟50

CSP模拟50

时间:2023-10-07 20:57:41浏览次数:46  
标签:int sum 50 sqrt long ans include CSP 模拟

T1 异或

赛时 \(8\) min 切了。


\[\sum\limits_{i=0}^{n-1} popcount(i\oplus (i+1)) \]

记 \(a_i=popcount(i\oplus (i-1))\),打个表可以发现 \(a_{[1,2^i]}\) 与 \(a_{[2^i+1,2^{i+1}]}\) 之间的关系,即 \(\forall j\in[1,2^i-1],a_{j+2^i}=a_j\),同时 \(a_{2^{i+1}}=a_{2^i}+1\)。

然后发现还挺对的,因为 \(\forall j\in[1,2^i-1]\),与 \(j+2^i\) 在二进制上的区别只有第 \(i\) 位(从第 \(0\) 位开始),但 \(j\) 与 \(j-1\) 的第 \(i\) 位都是 \(0\),\(j+2^i\) 与 \(j+2^i-1\) 的第 \(i\) 位都是 \(1\),所以 \(a_{j+2^i}=a_j\)。

同时对于 \(a_{2^i}\),发现等于 \(i+1\),挺显然的,所以后者也是对的。

所以 \(\sum\limits_{j=1}^{2^{i+1}}a_j=2\sum\limits_{j=1}^{2^i}a_j+1\)。

所以直接遍历 \(n\) 每一二进制位,为 \(1\) 的二进制位加上前缀贡献,时间复杂度 \(O(\log n)\)。

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
long long n,cur,ans;
int main()
{
#ifdef ONLINE_JUDGE
    cin.tie(0),cout.tie(0);
    ios::sync_with_stdio(0);
#endif
    cin>>n;
    while(n)
    {
        cur=cur*2+1;
        if(n&1) ans+=cur;
        n>>=1;
    }
    cout<<ans<<'\n';
    return 0;
}

T2 赌神

开始以为是什么牛逼博弈论直接跳了,后来发现后俩题做不出来回来一看诈骗题。

所以为啥赌博题能研究出来必定不亏啊?所以赌博的猫腻就在于他不能拥有足够多的单位注导致黑手操作使他必定亏吗?

好像本来也不会知道各种颜色球的个数,那没事了。


先要求玩家使用一种策略,记\(a_i\) 表示第 \(i\) 个球剩余了多少个,\(S=\sum\limits_{i=1}^n a_i\)。对于 \(\forall i\in[1,n]\) 下注 \(\text{现有本金}\times \dfrac{a_i}{S}\),那么这轮如果落下第 \(i\) 个球,下轮本金就变为这轮本金的 \(\dfrac{a_i}{S}\times n\) 倍。

发现这样很优,因为这样每次无论落下哪个球最终获得的收益是一定的,黑手无论怎样操作,最后总收益都是 \(\dfrac{\prod\limits_{i=1}^n a_i!}{S!}\times n^S\),相当于是乘法交换律。

然后证明这样最优,如果不这样操作,那么就肯定有至少一种球获得的收益要比原来低,相当于给了黑手操作空间,他会让这类球掉下来。但你发现你这样做并没任何作用,因为去掉这个球后变成了一个完全一样的子问题,也就是说你之后也不会比原来那种策略更优,最多也只是一样。所以肯定不会变优,故原来策略最优。

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=1e6+10,MOD=998244353;
int n,a[MAXN],sum;long long P[MAXN],ans=1;
inline long long ksm(long long a,int b)
{
    long long ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%MOD;
        a=a*a%MOD,b>>=1;
    }
    return ans;
}
int main()
{
#ifdef ONLINE_JUDGE
    cin.tie(0),cout.tie(0);
    ios::sync_with_stdio(0);
#endif
    cin>>n;P[0]=1;
    for(register int i=1;i<=1000000;++i) P[i]=P[i-1]*i%MOD;
    for(register int i=1;i<=n;++i)
        cin>>a[i],sum+=a[i],ans=ans*P[a[i]]%MOD;
    ans=ans*ksm(P[sum],MOD-2)%MOD*ksm(n,sum)%MOD;
    cout<<ans<<'\n';return 0;
}

T3 路径

不会,不想学,只会 \(70 pts\),干脆不写了。

原题-P4827 [国家集训队] Crash 的文明世界

T4 树

为啥模拟赛考 P7710 [Ynoi2077] stdmxeypz 啊。

Subtree distance modulo x equal y plus z

还挺有意思的,做法好像很多,但好像又大同小异。

主要就是根号分治,赛时想到了,但只想着 \(x\) 小时怎么从 \(x\) 大的基础上优化,所以分治不彻底,不触及根本,充分体现了 int_R 的软弱性与妥协性。

赛时只想到 \(O(n\sqrt n\log n)\),目测 \(10^5\) 过不去(虽然好像可以?),写了个完全可以被卡的没复杂度保证的线段树结果过了 \(10^5\),拿了 \(60\) pts。

然后去看了 Ynoi 题解写了正解其一,但没注意到那篇题解说要卡常,于是乎 HZOJ 过了,洛谷过不了。

代码写了好长,不如 5k 做法。


我:卡常没意义,不卡了。

5k:lxl 说过数据结构的本质就是卡常,你说卡常没有意义,就是说数据结构没有意义。

我:……

我:没事我放着,万一哪天……我不想写题了来卡卡常也是很好的。

5k:人话——咕了。

我:……

为啥今天写总结废话咋这么老多,虽然这句也是废话。


1 a x y z:把 \(a\) 子树中所有与 \(a\) 的距离模 \(x\) 等于 \(y\) 的节点权值加 \(z\)。

2 a:查询 \(a\) 节点的权值。

1 操作变为 \(a\) 子树中所有深度模 \(x\) 等于 \((y+dep_a)\bmod x\) 的节点权值加 \(z\) ,这样要好看一些。

子树,所以求出 dfs 序转化到序列上,然后考虑对 \(x\) 根号分治。

对于 \(x\) 小于等于 \(\sqrt n\),将每个询问拆成 \(\sqrt n\) 个。

具体的,先枚举 \(x:1\to \sqrt n\),再枚举余数 \(r:0\to x-1\),处理所有为 \(\operatorname{mod} x=r\) 形式的修改和 \(dep_a \bmod x=r\) 的所有询问。相当于区间加,单点查。

这一部分每个修改只执行 \(1\) 次,但每个询问需要处理 \(\sqrt n\) 次,平衡一下要求 \(O(\sqrt n)\) 区间加,\(O(1)\) 单点查,分块直接做。

对于 \(x\) 大于 \(\sqrt n\),将每个修改拆成 \(\sqrt n\) 个。

具体的,一个修改的形式是对于一些深度的点的,由于 \(x>\sqrt n\) ,所以这些深度的个数是 \(\sqrt n\) 级别的。于是可以将修改拆成 \(\sqrt n\) 个。也就是枚举深度 \(d:1\to n\),对于所有 \(d\bmod x=y\) 的修改操作和所有 \(dep_a=d\) 的查询操作进行处理,同样相当于区间加,单点查。

只不过这一部分每个修改执行 \(\sqrt n\) 次,每个询问处理 \(1\) 次,平衡一下要求 \(O(1)\) 区间加,\(O(\sqrt n)\) 单点查,差分一下仍然分块直接做。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<vector>
using namespace std;
const int MAXN=3e5+10,MAXT=550;
int n,q,T,to[MAXN<<1],nxt[MAXN<<1],head[MAXN],cur;
int dfn[MAXN],dep[MAXN],siz[MAXN],tot,ANS[MAXN];
struct node{int pos,a,x,y,z;}p[MAXN];
vector <node> v[MAXN];
namespace part
{
    int len,bel[MAXN],a[MAXN],sum[MAXT],lazy[MAXT],b[MAXT],e[MAXT];
    inline void init()
    {
        len=sqrt(n);
        for(register int i=1;i<=n;++i) bel[i]=(i-1)/len+1;
        for(register int i=1;i<=bel[n];++i)
            b[i]=(i-1)*len+1,e[i]=min(i*len,n);
        return ;
    }
    inline void change(int l,int r,int z)
    {
        if(bel[l]==bel[r])
        {
            for(register int i=l;i<=r;++i) a[i]+=z,sum[bel[i]]+=z;
            return ;
        }
        for(register int i=l;i<=e[bel[l]];++i) a[i]+=z,sum[bel[i]]+=z;
        for(register int i=b[bel[r]];i<=r;++i) a[i]+=z,sum[bel[i]]+=z;
        for(register int i=bel[l]+1;i<bel[r];++i) lazy[i]+=z;
        return ; 
    }
    inline int query(int l,int r)
    {
        int ans=0;
        if(bel[l]==bel[r])
        {
            for(register int i=l;i<=r;++i) ans+=a[i]+lazy[bel[i]];
            return ans;
        }
        for(register int i=l;i<=e[bel[l]];++i) ans+=a[i]+lazy[bel[i]];
        for(register int i=b[bel[r]];i<=r;++i) ans+=a[i]+lazy[bel[i]];
        for(register int i=bel[l]+1;i<bel[r];++i) ans+=sum[i]+lazy[i]*(e[i]-b[i]+1);
        return ans;
    }
};
inline void add(int x,int y)
{
    to[++cur]=y,nxt[cur]=head[x];
    head[x]=cur;return ;
}
void dfs(int x,int fa=0)
{
    dfn[x]=++tot,dep[x]=dep[fa]+1,siz[x]=1;
    for(register int i=head[x];i;i=nxt[i])
    {
        int y=to[i];if(y==fa) continue;
        dfs(y,x);siz[x]+=siz[y];
    }
    return ;
}
int main()
{
#ifdef ONLINE_JUDGE
    cin.tie(0),cout.tie(0);
    ios::sync_with_stdio(0);
#endif
    cin>>n>>q;T=sqrt(n);
    for(register int i=1;i<n;++i)
    {
        int x,y;cin>>x>>y;
        add(x,y),add(y,x);
    }
    dfs(1),part::init();
    for(register int i=1;i<=q;++i)
    {
        int opt,a,x=0,y=0,z=0;cin>>opt>>a;
        if(opt==1){cin>>x>>y>>z,y=(y+dep[a])%x;}
        p[i]={i,a,x,y,z};
    }
    for(register int i=1;i<=T;++i)
    {
        for(register int j=1;j<=q;++j)
        {
            if(p[j].x==i) v[p[j].y].push_back(p[j]);
            else if(!p[j].x) v[dep[p[j].a]%i].push_back(p[j]);
        }
        for(register int j=0;j<i;++j)
        {
            for(node k:v[j])
            {
                if(k.x) part::change(dfn[k.a],dfn[k.a]+siz[k.a]-1,k.z);
                else ANS[k.pos]+=part::query(dfn[k.a],dfn[k.a]);
            }
            for(node k:v[j])
                if(k.x) part::change(dfn[k.a],dfn[k.a]+siz[k.a]-1,-k.z);
            v[j].clear();
        }
    }
    for(register int j=1;j<=q;++j)
    {
        if(p[j].x>T)
            for(register int i=p[j].y;i<=n;i+=p[j].x) v[i].push_back(p[j]);
        else if(!p[j].x) v[dep[p[j].a]].push_back(p[j]);
    }
    for(register int i=1;i<=n;++i)
    {
        for(node k:v[i])
        {
            if(k.x)
            {
                part::change(dfn[k.a],dfn[k.a],k.z);
                part::change(dfn[k.a]+siz[k.a],dfn[k.a]+siz[k.a],-k.z);
            }
            else ANS[k.pos]+=part::query(1,dfn[k.a]);
        }
        for(node k:v[i])
            if(k.x)
            {
                part::change(dfn[k.a],dfn[k.a],-k.z);
                part::change(dfn[k.a]+siz[k.a],dfn[k.a]+siz[k.a],k.z);
            }
    }
    for(register int i=1;i<=q;++i) if(!p[i].x) cout<<ANS[i]<<'\n';
    return 0;
}

标签:int,sum,50,sqrt,long,ans,include,CSP,模拟
From: https://www.cnblogs.com/int-R/p/CSP50.html

相关文章

  • CSP模拟50联测12
    异或别笑我,考场上打的数位dp......
  • CF506D Mr. Kitayuta's Colorful Graph
    好久没更新这个单题系列了,主要是最近没啥CF比赛空闲时间又少,今天忙里偷闲写了两个题这个题就比较典了,两点是否连通一般都是想到并查集维护,现在的问题是要对每种颜色的边把贡献算清楚很容易想到枚举所有颜色的边,每次求出所有连通分量后遍历一遍询问统计答案,这样正确性显然但复杂......
  • 洛谷3501宝牌一大堆
    这道题很长一读完可以发现不是模拟题,那么这道题还有这么多情况供我们去讨论,则一般都是可以去掉一些情况的我们发现,对任意一种和牌,如果有杠子,我们把这个杠子换成少一张牌的刻字答案是会变得更优的(很简单的列算式)所以就不用考虑大于15张牌的情况了对于国士无双暴力即可对于七对......
  • 2023年10月7日模拟赛复盘
    题目列表T1Karma知识点:贪心、逆序对T2Desire知识点:树上差分、组合数T3Courage知识点:树上DPT4Innocent知识点:tarjan求强连通分量,有负权最短路复盘2023年10月7日记:第一題穩拿,後面部分分打得非常糟糕,死磕一道題磕不出來的嚴重後果,,!\(\color{Gray}{p.s.就是喜......
  • LY1371 [ 20231007 NOIP 模拟赛 T0 ] 十一之争
    题意给定一个长度为\(n\)的数字串\(s\)和只包含yo的字符串\(t\),yoimiya会和oimiya玩\(n\)轮游戏,初始有一个数字串\(x\)为\(0\),每次:如果\(t_i\)是y则是yoimiya操作,如果是o则是oimiya操作。每次操作:将\(s_i\)或者\(0\)加入\(x\)的末尾。如果最......
  • gpio模拟功能介绍
    gpio模拟状态是gpio功能的一种,此状态下,gpio斯密特触发器关闭状态,上下拉状态开关关闭一般低功耗的模式下会将不用的gpio设置为模拟状态。 参考:基于CubeMx管脚配置时的ADC_IN与GPIO_Analog选项话题-知乎(zhihu.com)......
  • 实现redis哨兵,模拟master故障场景
     1.概述 在哨兵(sentinel)机制中,可以解决redis高可用问题,即当master故障后可以自动将slave提升为master,从而可以保证redis服务的正常使用。2.哨兵的实现 哨兵的前提是已经实现了一个redis的主从复制的运行环境,从而实现一个一主两从基于哨兵的高可用redis架构。注意:......
  • 23/10/06 模拟赛总结
    时间安排7:35-7:45看题。A题一眼秒,BC没思路,D树形DP。7:45-7:50随便过了A题。7:50-8:50写B题暴力的时候被卡了,时间复杂度怎么算都会T第一档分,也没什么好的处理方法,最后感觉应该跑不满就直接写了纯暴力。8:50-9:30思考C,写了爆搜,\(n,m\leq20\)想了一个......
  • 33dai NOIP2023模拟赛35 赛后总结
    做题历程8:00~8:40写A。8:40~9:40看B,C想B,写B。9:40~10:40手玩了一下C,推出了那个规律。10:40~11:20写C。11:20~12:00看了看D,尝试写dp暴力,没空,最后随便写了写。总结写代码要注意细节,不然容易挂。题解A倒序做一遍双指针,没什么好说的。不过有很多人用奇......
  • Top 50+ Linux Commands You MUST Know
     https://www.digitalocean.com/community/tutorials/linux-commands Top50LinuxCommandsYouMustKnowasaRegularUserls-ThemostfrequentlyusedcommandinLinuxtolistdirectoriespwd-PrintworkingdirectorycommandinLinuxcd-Linuxcomman......