• 【考试总结】20220410


    也许

    维护 \(S\) 集合形成的线性基,答案就是 \(2^{n-\rm{rank}}\)

    动态维护写一个带删除线性基即可

    Code Display
    const int N=2e6+10;
    int n,Q,ans,nxt[N];
    struct  Linear_Basis{
        int t[40],cnt,b[40];
        inline void insert(int v,int tim){
            for(int i=30;i>=0;--i) if(v>>i&1){
                if(b[i]){
                    if(t[i]<tim) swap(tim,t[i]),swap(v,b[i]);
                    v^=b[i];
                }else ++cnt,t[i]=tim,b[i]=v,i=0;
            }
            return ;
        }
    }B;
    unordered_map<int,int> mp;
    int opt[N],x[N];
    signed main(){
        freopen("A.in","r",stdin); freopen("A.out","w",stdout);
        n=read(); Q=read();
        for(int i=1;i<=Q;++i){
            opt[i]=read(); x[i]=read();
            if(opt[i]==1){
                mp[x[i]]=i;
            }else{
                nxt[mp[x[i]]]=i;
                mp.erase(x[i]);
            }
        }
        for(int i=1;i<=Q;++i) if(opt[i]==1&&!nxt[i]) nxt[i]=Q+1;
        for(int i=1;i<=Q;++i){
            if(opt[i]==1) B.insert(x[i],nxt[i]);
            else{
                for(int j=30;j>=0;--j) if(B.t[j]==i){
                    B.t[j]=B.b[j]=0;
                    --B.cnt;
                }
            }
            assert(!B.b[30]);
            ans^=1ll<<(n-B.cnt);
        }
        print(ans);
        return 0;
    }
    

    这就是

    \(f_{i,S}\) 表示 \(S\) 中的元素分成了 \(i\) 中不同的权值层,转移每次加入一个子集即可

    根据实际含义,加入的新集合需要满足 \((R,id)\) 的最小值,对应的元素方案数也就是 \(\min-\rm num\) ,其中 \(\rm num\) 是已经分出来的集合个数

    时间复杂度 \(\Theta(n3^n)\)

    乍一看是不能通过集合幂级数 \(\exp\) 往下降复杂度的,因为我不会集合幂级数求导

    Code Display
    int dp[1<<15],mn[1<<15],r[20],g[1<<15],n,m;
    signed main(){
        freopen("B.in","r",stdin); freopen("B.out","w",stdout);
        n=read(); m=read();
        rep(i,1,n) r[i]=read()+1;
        int U=1<<n; --U;
        mn[0]=r[0]=mod;
        for(int i=1;i<=U;++i){
            int lb=i&(-i);
            mn[i]=min(mn[i^lb],r[__builtin_ctz(lb)+1]);
        }
        while(m--){
            int u=read(),v=read();
            for(int i=1;i<=U;++i){
                bool c1=i>>(u-1)&1;
                bool c2=i>>(v-1)&1;
                if(c1&&c2) mn[i]=0;
            }
        }
        for(int i=1;i<=U;++i){
            int tmp=i;
            while(tmp){
                int lb=tmp&(-tmp);
                int id=__builtin_ctz(lb)+1;
                tmp^=lb;
                if(r[id]<r[g[i]]) g[i]=id;
            }
        }
        int ans=0;
        dp[0]=1;
        for(int i=0;i<n;++i){
            for(int S=U;~S;--S){
                dp[S]=0;
                for(int T=S;T;T=(T-1)&S) if(T>>(g[U^(S^T)]-1)&1){
                    ckadd(dp[S],mul(dp[S^T],max(0ll,mn[T]-i)));
                }
            }
            ckadd(ans,mul(dp[U],i+1));
        }
        print(ans);
        return 0;
    }
    

    人生吧

    使用 \(e[p^e\ | \ gcd,p^{e+1}\not|\ gcd]=\sum_{e\ge 1}[p^e|gcd]\) 来计算区间元素所包含的某个因子 \(p\) 的贡献

    如果现在已知有 \(x\) 个元素唯一分解中 \(p\) 的指数 \(\ge e\) 那么再加入 \(p^e\) 新增的贡献是 \(p^{2^x}\)

    此时可以使用莫队维护,注意 \(p\) 的贡献都是 \(p^{2^x}\) 的形式,那么对于所有可行的 \((p,x)\) 预处理出来即可

    Code Display
    int pri[N],cnt,a[N],n,Q,d[N],bl[N],block;
    bool fl[N];
    vector<pair<int,int> > Div[N];
    struct Query{int l,r,id;}q[N];
    vector<int> pw[N],ipw[N];
    int ton[N][20],cur=1,ans[N];
    int pw2[N];
    inline void insert(int id){
        for(auto pr:Div[id]){
            int p=pr.fir,e=pr.sec;
            for(int t=1;t<=e;++t){
                ckmul(cur,pw[p][ton[p][t]]);
                ton[p][t]++;
            }
        }
        return ;
    }
    inline void erase(int id){
        for(auto pr:Div[id]){
            int p=pr.fir,e=pr.sec;
            for(int t=1;t<=e;++t){
                ton[p][t]--;
                ckmul(cur,ipw[p][ton[p][t]]);
            }
        }
        return ;
    }
    int sum[N];
    signed main(){
        freopen("C.in","r",stdin); freopen("C.out","w",stdout);
        n=1e5;
        pw2[0]=1; pw2[1]=2;
        for(int i=2;i<=n;++i){
            if(!fl[i]) pri[++cnt]=i,d[i]=i;
            for(int j=1;i*pri[j]<=n&&j<=cnt;++j){
                fl[i*pri[j]]=1; d[i*pri[j]]=pri[j];
                if(i%pri[j]==0) break;
            }
            pw2[i]=mul(pw2[i-1],2,mod-1);
        }
        for(int i=1;i<=n;++i){
        }
        n=read(); Q=read(); block=sqrt(Q);
        rep(i,1,n){
            a[i]=read();
            int x=a[i];
            while(x>1){
                int v=d[x],tim=0;
                while(x%v==0) x/=v,tim++;
                Div[i].emplace_back(v,tim);
                sum[v]++;
            }
        }
        for(int i=1;i<=cnt;++i) if(sum[pri[i]]){
            pw[pri[i]].resize(1+sum[pri[i]]);
            pw[pri[i]][0]=pri[i];
            ipw[pri[i]].resize(1+sum[pri[i]]);
            ipw[pri[i]][0]=ksm(pri[i],mod-2);
            for(int j=1;j<=sum[pri[i]];++j){
                pw[pri[i]][j]=mul(pw[pri[i]][j-1],pw[pri[i]][j-1]);
                ipw[pri[i]][j]=mul(ipw[pri[i]][j-1],ipw[pri[i]][j-1]);
            }
        }
        for(int i=1;i<=Q;++i) q[i].l=read(),q[i].r=read(),q[i].id=i,bl[i]=(i-1)/block+1;
        sort(q+1,q+Q+1,[&](const Query &a,const Query &b){
            if(bl[a.l]==bl[b.l]) return a.r<b.r;
            return bl[a.l]<bl[b.l]; 
        });
        int l=1,r=0;
        for(int i=1;i<=Q;++i){
            while(r<q[i].r) insert(++r);
            while(l>q[i].l) insert(--l);
            while(l<q[i].l) erase(l++);
            while(r>q[i].r) erase(r--);
            ans[q[i].id]=cur;
        } 
        rep(i,1,Q) print(ans[i]); 
        return 0;
    }
    

  • 相关阅读:
    解决小问题VC2008通过ADO连接ACCESS (转)
    给zblog站点备份和搬家
    vc中自定义编译时的输出消息 .
    更改MFC 对话框控件的tab顺序
    dotnetbar 添加到工具栏方法
    关于完成端口IOCP异步接收连接函数AcceptEx注意事项 (转)
    中英文url解码vc++源程序
    c#关于网页内容抓取,简单爬虫的实现。(包括动态,静态的)
    图解使用Broadcom Advanced Control Suite 2设置Broadcom单网卡跨多VLAN(转)
    windbg调试环境变量记录
  • 原文地址:https://www.cnblogs.com/yspm/p/16126741.html
Copyright © 2020-2023  润新知