首页 > 其他分享 >NOIP 模拟13(NOIP A层联测26)

NOIP 模拟13(NOIP A层联测26)

时间:2023-11-07 20:01:49浏览次数:41  
标签:13 return NOIP int 26 MAXN ans include dis

100+100+20+17,T3 按理说应该想到考虑两部分分别的贡献的,明明这个套路很常见。

5k:就喜欢这种数据结构专场,多来点。

A.origen

先前缀和,以下 \(p_i\) 表示前缀异或和。

考虑将一个数 \(k\) 二进制差分,假设拆成 \(2^a+2^b+2^c\),则 \(k^2=(2^a+2^b+2^c)\times(2^a+2^b+2^c)\),也就是指数两两结合。

所以一个数的平方就相当于 \(k^2=\sum\limits_{i=0}^{\lfloor\log_2{k^2}\rfloor} 2^i\times \sum\limits_{j=0}^{i} [k\operatorname{bitand} 2^j][k\operatorname{bitand} 2^{i-j}]\)。所以我们考虑统计所有原序列子区间异或和的第 \(x\) 位与第 \(y\) 位。

设 \(f_{i,x,y,0/1,0/1}\) 为在 \(1\sim i\) 当中,\(a_i\) 的第 \(x,y\) 二进制位为 \(0/1,0/1\) 的个数,\(ans_i\) 为所有 \(k^2\) 中 \(2^i\) 的个数。

设 \(w1=[p_i\operatorname{bitand} 2^x],w2=[p_i\operatorname{bitand} 2^y]\)。

有转移 \(ans_{x+y}=ans_{x+y}+f_{i-1,x,y,w1\oplus 1,w2\oplus 1},f_{i,x,y,w1,w2}=f_{i-1,x,y,w1,w2}+1\)。

最后统计答案即可,第一维可滚掉,时间复杂度 \(O(n\log^2 n)\)。

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=2e5+10,MOD=998244353;
int n,a[MAXN];long long ans[50],f[20][20][2][2];
int main()
{
    freopen("origen.in","r",stdin);
    freopen("origen.out","w",stdout);
    cin.tie(0),cout.tie(0);
    ios::sync_with_stdio(0);
    cin>>n;for(int i=1;i<=n;++i) cin>>a[i],a[i]^=a[i-1];
    for(int x=0;x<18;++x)
        for(int y=0;y<18;++y)
            f[x][y][0][0]=1;
    for(int i=1;i<=n;++i)
    {
        for(int x=0;x<18;++x)
            for(int y=0;y<18;++y)
            {
                ans[x+y]+=f[x][y][(a[i]>>x)&1^1][(a[i]>>y)&1^1];
                f[x][y][(a[i]>>x)&1][(a[i]>>y)&1]++;
                ans[x+y]%=MOD;
            }
    }
    long long ANS=0,P=1;
    for(int i=0;i<36;++i)
    {
        ANS+=P*ans[i]%MOD;
        P=P*2%MOD;
    }
    cout<<ANS%MOD<<'\n';return 0;
}

B.competition

考虑统计所有组“每组中不能做出来的题数之和”\(sum\),记总组数 \(N=\dfrac{n(n+1)}{2}\),最终答案为 \(\dfrac{Nm-sum}{N}\)。

如果你从 \(1\to n\) 扫描,维护出来每道题最后能做出来的时间 \(t_i\),那么你选择的以 \(i\) 结尾的区间的不能做出来的题数之和就等于 \(im-\sum\limits_{j=1}^{m} t_j\),(\(im\) 因为有 \(i\) 个区间)。

要维护全局和,区间赋值,线段树即可,动态开点被卡空间,离散化即可。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int MAXN=1e6+10,MOD=1e9+7;
int n,cnt=1,tot,p;ll m,l[MAXN],r[MAXN],ans;
ll a[MAXN<<1],b[MAXN<<2],len[MAXN<<2];
struct tree{int num,add,len;}t[MAXN<<4];
void build(ll l,ll r,int p)
{
    if(l==r){t[p].len=len[l];return ;}
    ll mid=(l+r)>>1;
    build(l,mid,p<<1),build(mid+1,r,p<<1|1);
    t[p].len=(t[p<<1].len+t[p<<1|1].len)%MOD;return ;
}
inline void change(ll l,ll r,int p,ll x,ll y,ll z)
{
    if(x<=l&&y>=r)
    {
        t[p].num=1ll*t[p].len*z%MOD;
        t[p].add=z;return ;
    }
    ll mid=(l+r)>>1;
    if(t[p].add)
    {
        t[p<<1].num=1ll*t[p<<1].len*t[p].add%MOD;
        t[p<<1|1].num=1ll*t[p<<1|1].len*t[p].add%MOD;
        t[p<<1].add=t[p].add,t[p<<1|1].add=t[p].add;
        t[p].add=0;
    }
    if(x<=mid) change(l,mid,p<<1,x,y,z);
    if(y>mid) change(mid+1,r,p<<1|1,x,y,z);
    t[p].num=(t[p<<1].num+t[p<<1|1].num)%MOD;return ;
}
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()
{
    freopen("competition.in","r",stdin);
    freopen("competition.out","w",stdout);
    cin.tie(0),cout.tie(0);
    ios::sync_with_stdio(0);
    cin>>n>>m;
    for(int i=1;i<=n;++i)
        cin>>l[i]>>r[i],a[++tot]=l[i],a[++tot]=r[i];
    a[++tot]=0,a[++tot]=m;sort(a+1,a+1+tot);
    for(int i=1;i<=tot;++i)
    {
        if(i!=1&&a[i]==a[i-1]) continue;
        if(i!=1&&a[i]!=a[i-1]+1)
            b[++p]=a[i-1]+1,len[p]=(a[i]-a[i-1]-1)%MOD;
        b[++p]=a[i],len[p]=1;
    }
    for(int i=1;i<=n;++i)
        l[i]=lower_bound(b+1,b+1+p,l[i])-b,
        r[i]=lower_bound(b+1,b+1+p,r[i])-b;
    build(1,p,1);
    for(int i=1;i<=n;++i)
    {
        change(1,p,1,l[i],r[i],i);
        ans+=(m%MOD*i%MOD-t[1].num+MOD)%MOD;
    }
    ll N=1ll*n*(n+1)/2%MOD;
    cout<<(m%MOD*N%MOD-ans%MOD+MOD)%MOD*ksm(N,MOD-2)%MOD<<'\n';
    return 0;
}

C.tour

发现最多连成一棵树,每次就是在森林中选取两个树合并。

拆路径,记 \(L=lca(x,y)\),\(x\to y\) 拆成 \(x\to L,L\to y\)。

记 \(dis_i\) 为 \(i\) 到根路径上的权值和。

第一段 \(i\in x\to L\) 满足条件,等价于 \(dis_x-dis_i\geq a_i\)。

第二段 \(i\in L\to y\) 满足条件,等价于 \((dis_x-dis_L+a_L)+(dis_i-dis_L-a_i)\geq a_i\)。

移项,主席树维护点到根信息,转换成树链上小于等于某个数个数。合并启发式合并暴力重构,感觉平凡,但我赛时没想到。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int MAXN=1e5+10,INF=500010000;
int testmode,lastans,n,q,a[MAXN],dis[MAXN];
int dep[MAXN],f[MAXN][20],fa[MAXN],siz[MAXN];
vector <int> v[MAXN];
struct segment_tree
{
    int root[MAXN],cnt;
    struct tree{int num,ls,rs;}t[MAXN<<8];
    inline void change(int l,int r,int p,int q,int x)
    {
        t[q].ls=t[p].ls,t[q].rs=t[p].rs;
        if(l==r){t[q].num=t[p].num+1;return ;}
        int mid=(l+r)>>1;
        if(x<=mid) change(l,mid,t[p].ls,t[q].ls=++cnt,x);
        else change(mid+1,r,t[p].rs,t[q].rs=++cnt,x);
        t[q].num=t[t[q].ls].num+t[t[q].rs].num;return ;
    }
    inline int query(int l,int r,int p,int q,int x,int y)
    {
        if(x<=l&&y>=r) return t[q].num-t[p].num;
        int mid=(l+r)>>1,ans=0;
        if(x<=mid) ans+=query(l,mid,t[p].ls,t[q].ls,x,y);
        if(y>mid) ans+=query(mid+1,r,t[p].rs,t[q].rs,x,y);
        return ans;
    }
}X,Y;
inline void work(int i,int fa)
{
    X.change(-INF,INF,X.root[fa],X.root[i]=++X.cnt,a[i]+dis[i]);
    Y.change(-INF,INF,Y.root[fa],Y.root[i]=++Y.cnt,2*a[i]-dis[i]);
    return ;
}
inline int lca(int x,int y)
{
    if(dep[x]<dep[y]) swap(x,y);
    while(dep[x]>dep[y]) x=f[x][__lg(dep[x]-dep[y])];
    if(x==y) return x;
    for(register int i=__lg(dep[x]);i>=0;--i)
        if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    return f[x][0];
}
void dfs(int x,int fa=0)
{
    for(int i=0;i<=__lg(dep[x]);++i) f[x][i]=0;
    dep[x]=dep[fa]+1,dis[x]=dis[fa]+a[x];
    f[x][0]=fa,work(x,fa);
    for(int i=1;i<=__lg(dep[x]);++i)
        f[x][i]=f[f[x][i-1]][i-1];
    for(int y:v[x]) if(y!=fa) dfs(y,x);
    return ;
}
inline int find(int x){return (x==fa[x])?x:fa[x]=find(fa[x]);}
int main()
{
    freopen("tour.in","r",stdin);
    freopen("tour.out","w",stdout);
    cin.tie(0),cout.tie(0);
    ios::sync_with_stdio(0);
    cin>>testmode>>n>>q;
    for(int i=1;i<=n;++i)
        cin>>a[i],dep[i]=1,dis[i]=a[i],work(i,0),fa[i]=i,siz[i]=1;
    while(q--)
    {
        int opt,x,y;cin>>opt>>x>>y;
        if(testmode) x^=lastans,y^=lastans;
        if(opt==0)
        {
            v[x].push_back(y),v[y].push_back(x);
            int fax=find(x),fay=find(y);
            if(siz[fax]<siz[fay]) swap(x,y),swap(fax,fay);
            siz[fax]+=siz[fay],fa[fay]=fax,dfs(y,x);
        }
        else
        {
            int L=lca(x,y),ans=0;
            ans+=X.query(-INF,INF,X.root[f[L][0]],X.root[x],-INF,dis[x]);
            ans+=Y.query(-INF,INF,Y.root[L],Y.root[y],-INF,dis[x]+a[L]-2*dis[L]);
            cout<<(lastans=ans)<<'\n';
        }
    }
    return 0;
}

D.abstract

好像有意思,先咕。

标签:13,return,NOIP,int,26,MAXN,ans,include,dis
From: https://www.cnblogs.com/int-R/p/NOIP-A-26.html

相关文章

  • CF1359D Yet Another Yet Another Task
    貌似没有线段树做法。记\(s\)为\(a\)的前缀和数组。对于一个确定的右端点\(r\)和左端点\(l\),它对于答案的贡献是\(s_r-s_{l-1}-max\{a_i\},l\lei\ler\),如果枚举右端点,令\(c_l=s_{l-1}+max\{a_i\},l\lei\)。那么其实就是要求\(1\lek\ler-1\)的\(min\{c_k\}\)。线......
  • [NOIP2012 提高组] 开车旅行
    题目描述小AA和小BB决定利用假期外出旅行,他们将想去的城市从11到nn编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市ii的海拔高度为hihi​,城市ii和城市jj之间的距离di,jdi,j​恰好是这两个城市海拔高度之差的绝对值,即di,j=∣h......
  • mac os13上安装apache\php\mysql
    macos13上安装1,下载并安装brew,brew是macos上的软件安装工具;2,安装apache2brewinstallhttpd 安装成功后提示:工程文件根目录DocumentRootis/usr/local/var/www配置文件Thedefaultportshavebeensetin/usr/local/etc/httpd/httpd.confto8080andin/usr/local/e......
  • 文心一言 VS 讯飞星火 VS chatgpt (130)-- 算法导论11.2 2题
    二、用go语言,对于一个用链接法解决冲突的散列表,说明将关键字5,28,19,15,20,33,12,17,10插入到该表中的过程。设该表中有9个槽位,并设其散列函数为h(k)=kmod9。文心一言:在这个问题中,我们使用Go语言来解决一个散列(Hash)表的问题,该问题需要我们使用链接法解决冲突。我们的散......
  • 《安富莱嵌入式周报》第326期:航空航天级CANopen协议栈,开源USB PD电源和功耗分析,开源Et
    周报汇总地址:http://www.armbbs.cn/forum.php?mod=forumdisplay&fid=12&filter=typeid&typeid=104 更新一期视频教程:BSP视频教程第28期:CANopen协议栈专题,CANopen主从机组网实战,CAN词典工具使用方法以及吃透PDO玩法https://www.armbbs.cn/forum.php?mod=viewthread&tid=12161......
  • day1311
    后缀分类动词后缀-ize(做成;变成;..........化)modernize(现代化)-en(使成为;引起)quicken(加快)-fy(使........化;使成)purify(净化)-ish(使;令)abolish(取消)-ate(成为........;处理)indicate(指示)形容词后缀-able/-ibleflexible(可弯......
  • Day13
    科技发展中的英语词汇工业革命时期英语词汇的特点借词旧词赋新义英语扩张古英语留中古英语引现代英语借词根以及词根的分类什么是词源学?Etymologytheoriginsofwordsthehistoryofwordsthechangingmeaningofwords词源、词根、词缀的关系......
  • 207-nginx 或者tomcat报错:413 Request Entity Too Large
    http{#...client_max_body_size20M;#设置最大允许大小为20MB#...}tomcat413RequestEntityTooLarge<Connectorport="8080"protocol="HTTP/1.1"connectionTimeout="20000"redirectPort=&quo......
  • 力扣1370 直接模拟
    1370. 上升下降字符串按照题目模拟创建了一个长度为26的数组来存放字母数量kk是结果res的实时长度,cs是第几次(来决定添加最小的还是添加最大的)classSolution{public:stringsortString(strings){stringres;intarr[26]={0};intsize=26;......
  • NOIP2023模拟12联测33 总结
    NOIP2023模拟12联测33总结目录NOIP2023模拟12联测33总结比赛过程正解A.构造题目大意思路思路B.游戏题目大意思路C.数数题目大意D.滈葕题目大意思路总结比赛过程先看了一眼\(T1\),发现又是恶心构造题,果断跳过。\(T2\)期望题,这么恶心吗,果断跳过。看看\(T3\)发现好像有......