zoukankan      html  css  js  c++  java
  • NOI 模拟赛 #2

    得分非常惨惨,半个小时写的纯暴力 70 分竟然拿了 rank 1。。。

    如果 OYJason 和 wxjor 在可能会被爆踩吧

    T1 欧拉子图

    给一个无向图,如果一个边集的导出子图是一个欧拉回路,则 ans 加上这个边集边数的平方,求 ans ,膜 998244353

    $n,m leq 152501$

    sol:

    考虑如果边数不是平方,而是一次方,那对于每个边,它对 ans 的贡献就是强行选它的方案数

    如果是平方,贡献就是枚举两个边 $x,y$ ( $x,y$ 可以相同),计算强制选它们的方案数

    Task #1 $n leq 60,m leq 100$

    需要一个多项式算法计算强制包含两条边的欧拉子图方案数

    我们把每个点看成一个关于度数的方程,设 $x_i$ 表示第 i 条边选不选,对第 j 个方程 $a_{(j,i)}$ 为 [第 i 条边的端点为 j]

    因为每个点度数都要为偶数,于是方程的右边都要在膜 2 意义下为 0

    钦定两条边选不选很简单,加 $x_a = 1$ 和 $x_b = 1$ 两个方程即可,这个方程组有多少解,强行选这两个边的方案数就有多少

    高斯消元,方案数就是 $2^c$ (c 为自由元个数)

    因为在膜 2 意义下进行,可以 bitset 优化一下,复杂度 $O(frac{n^2 imes m^3}{64})$,这个数据范围很好过

    bitset 实战很快,可以在 1s 内消 2000 的 xor 方程组


    Task #2 $n,m leq 300$

    随便搞一个 dfs 树,“强制选两个边”就是删掉两条边,钦定一些点度数为奇数,剩下为偶数,可以强行 dp 一下,由于跟正解没啥关系,略去


    Task #正解 $n,m leq 152501$

    延续 Task #1 的思路,注意到不同连通分量是独立的

    对于一个连通图有多少个欧拉子图呢?观察方程组可以发现是 $2^{m-n+1}$ 个

    不连通呢?设 $s$ 为联通块个数,发现是 $2^{m-n+s}$ 个

    现在我们要钦定选两条边,发现如果钦定到了一条桥边,肯定是不行的,因为桥两边度全变成了奇数,而之后只能不断加若干偶数

    然后发现,删掉两条不是桥的边,其实是可以改变图连通性的,如果连通性不变,连通块是 $2^{m-n+s-2}$ 个,如果改变,连通块是 $2^{m-n+s-1}$ 个

    于是问题变成了“有多少种 [删掉两条都不是桥边的边] 的方式,使得图不连通”

    前置问题:DZY Loves Chinese II (直接放链接了)

    给一个无向图,每次询问如果删掉一个边集,图是否依然连通,每次删掉的边集大小不超过 15

    还是非树边 ran 一下,树边 xor 一下,如果两个边权值一样,删掉它们就会改变连通性,用 map 记一下每种权值就可以了

    复杂度 $O(mlogm)$

    T2 求和

    求一个积性函数前缀和,这个函数满足 $f_{p^d} = p^{d-[d space mod space p ≠ 0]}$

    $n leq 10^{14}$

    sol:

    Task #1 $n leq 10^7$

    线性筛基本操作


    Task #2 & #3 $n leq 10^{12}$

    杜教筛基本操作,写的不好只能过 $n leq 10^9$ 的点

    但出题人说 Task #2 是给分块打表的...

    打表之后就是一个区间筛,我们把不超过 $sqrt{n}$的素数加进去筛一下就行了


    Task #正解 $n leq 10^{14}$

    构造 $ G = F * μ $ (狄利克雷卷积),显然当 $d = 1$ 时 $G(p) = 0$

    [狄利克雷卷积] $μ * 1 = [n=1]$,$phi * 1 = n$

    $G_n = sum_{d|n}f_d imes μ_{frac{n}{d}}$

    发现 $G_{p^c} = f_{p^c} - f_{p^{(c-1)}}$

    $G_p = f_p imes μ_1 + f_1 imes μ_p = 0$

    然后 $G_n = G_{p_1^{c_1}} imes G_{p_2^{c_2}} imes ... imes G_{p_n^{c_n}}$

    于是 $n = a^2 imes b^3$(这一步是某 $a imes b - a- b$ 定理)

    莫比乌斯反演 :$G = f * μ$ 则 $f = G * 1$

    $f_n = sum_{d|n}G_d$

    答案就是$$sum_{i=1}^n sum_{d|i}G_d = sum_{d=1}^{n}G_d imes lfloor frac{n}{d} floor$$

    满足 $n = a^2 imes b^3$ 的 $n$ 的数量是 $O(sqrt{n})$ 的,搜出来即可

    T3 数学难题

    $F_{(i,j)} = frac{(i+1)!}{j!(i-j)!}$

    $q$ 次求 $F_n$ 的前 $k$ 项的 lcm,强制在线

    $n,q leq 152501$

    sol:

    Task #1 & #2 $n leq 1000$

    发现矩阵是杨辉三角的第 i 行乘以 i 的值,暴力即可

    Task #正解 $n leq 152501$

    构造一下可以发现答案是 $lcm(n-k+1,n-k+2,...,n)$

    构造数组 $A_i[]$ 使得 $prod_{j=l}^r A_r[j] = lcm(l,...,r)$

    从小到大枚举 $n$ ,令 $A_n = A_{n-1},A_n[n] = n$,将 $n$ 质因数分解,若包含 $p^q$ 考虑修改 $m < n$ 的 $A_n[m]$

    设 $m$ 中含 $p^r$ 若 $r leq q$ 则 $A_n[m] /= p^r$,否则将 $A_n[m] /= p^q$,同时修改 $r$

    用一个栈维护每个有质因数的下标位置即可

    用可持久化线段树模拟,复杂度为 $O(nlog^2n + qlogn)$

    放放 std 吧

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #include<map>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    typedef long long ll;
    typedef unsigned long long ull;
    const int maxn=800010;
    const int mod=998244353;
    int n,m;
    int first[maxn],nxt[maxn],to[maxn],e;
    void AddEdge(int u,int v) {
        to[e]=v;nxt[e]=first[u];first[u]=e++;
        to[e]=u;nxt[e]=first[v];first[v]=e++;
    }
    ull rnd() {
        ull res=rand()^(rand()<<16);
        res<<=32;
        res|=rand()^(rand()<<16);
        return res;
    }
    int vis[maxn],vis2[maxn],clo;
    ull val[maxn],ev[maxn];
    ll cnt,all,ans;
    map<ull,int> M;
    void dfs(int x,int la) {
        vis[x]=++clo;
        for(int i=first[x];~i;i=nxt[i]) if(i!=(la^1)) {
            if(!vis[to[i]]) dfs(to[i],i);
            else if(vis[to[i]]<vis[x]) {
                ev[i]=rnd();cnt++;all++;
                val[x]^=ev[i];
                val[to[i]]^=ev[i];
                M[ev[i]]++;
            }
        }
    }
    void dfs2(int x,int la) {
        vis2[x]=++clo;
        for(int i=first[x];~i;i=nxt[i]) if(i!=(la^1)&&!vis2[to[i]]) {
            dfs2(to[i],i),val[x]^=val[to[i]];
        }
        if(val[x]) {
            all++;
            (cnt+=2*M[val[x]]+1)%=mod;
            M[val[x]]++;
        }
    }
    int main() {
        freopen("graph.in","r",stdin);
        freopen("graph.out","w",stdout);
        srand(52501);
        n=read(),m=read();
        memset(first,-1,sizeof(first));
        rep(i,1,m) AddEdge(read(),read());
        int tmp=m-n-2,res=1,res2=1;
        rep(i,1,n) if(!vis[i]) {
            dfs(i,-1),tmp++;
            dfs2(i,-1);
        }
        rep(i,1,tmp) res=(res+res)%mod;
        rep(i,1,tmp+1) res2=(res2+res2)%mod;
        all=(all*all-cnt)%mod;
        ans=(res2*cnt%mod+res*all%mod)%mod;
        printf("%lld
    ",ans);
        return 0;
    }
    T1
    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #include<vector>
    #define pb push_back
    #define mp make_pair
    #define xx first
    #define yy second
    #define rep(i,a,b) for(int i=(a),i##_end_=(b);i<=i##_end_;i++)
    #define dwn(i,a,b) for(int i=(a),i##_end_=(b);i>=i##_end_;i--)
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    const int maxn=10000010; 
    int pri[maxn/10],cnt;
    bool vis[maxn];
    void init(int n) {
        rep(i,2,n) {
            if(!vis[i]) pri[++cnt]=i;
            rep(j,1,cnt) {
                if(i*pri[j]>n) break;
                vis[i*pri[j]]=1;
                if(i%pri[j]==0) break;
            }    
        }
    }
    ll ans,n;
    void dfs(int cur,ll g,ll last) {
        ans+=g*last;
        rep(i,cur+1,cnt) {
            ll tmp=last;
            if((ll)pri[i]*pri[i]<=last) {
                tmp/=pri[i];tmp/=pri[i];
                ll p1=pri[i],p2=1,res;
                rep(d,2,60) {
                    if(!tmp) break;
                    res=p1*(d%pri[i]==0?pri[i]:1)-p2*((d-1)%pri[i]==0?pri[i]:1);
                    dfs(i,g*res,tmp);
                    tmp/=pri[i];
                    p1=p1*pri[i];
                    p2=p2*pri[i];
                }
            }
            else break;
        }
    }
    int main() {
        freopen("sum.in","r",stdin);
        freopen("sum.out","w",stdout);
        init(10000000);
        scanf("%lld",&n);
        dfs(0,1,n);
        printf("%lld
    ",ans);
        return 0;
    }
    T2
    #include<cstdio>
    #include<stack>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #include<vector>
    #define pb push_back
    #define mp make_pair
    #define xx first
    #define yy second
    #define rep(i,a,b) for(int i=(a),i##_end_=(b);i<=i##_end_;i++)
    #define dwn(i,a,b) for(int i=(a),i##_end_=(b);i>=i##_end_;i--)
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    typedef long long ll;
    typedef pair<int,int> pii;
    const int maxn=160010;
    const int mod=998244353;
    const int maxnode=15000010;
    int inv[maxn],ls[maxnode],rs[maxnode],mulv[maxnode],ToT;
    void update(int& y,int x,int l,int r,int p,int la,int v) {
        mulv[y=++ToT]=(ll)mulv[x]*inv[la]%mod*v%mod;
        if(l==r) return;int mid=l+r>>1;
        ls[y]=ls[x];rs[y]=rs[x];
        if(p<=mid) update(ls[y],ls[x],l,mid,p,la,v);
        else update(rs[y],rs[x],mid+1,r,p,la,v);
    }
    int query(int o,int l,int r,int ql,int qr) {
        if(!o) return 1;
        if(ql<=l&&r<=qr) return mulv[o];
        int mid=l+r>>1,res=1;
        if(ql<=mid) res=query(ls[o],l,mid,ql,qr);
        if(qr>mid) res=(ll)res*query(rs[o],mid+1,r,ql,qr)%mod;
        return res;
    }
    vector<pii> fac[maxn];
    stack<pii> S[maxn];
    int vis[maxn],root[maxn],pw[30],P;
    int calc(int n,int k) {return query(root[n],1,P,n-k+1,n);}
    void solve(int n) {
        inv[1]=1;
        rep(i,2,n) inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;
        mulv[0]=pw[0]=1;
        rep(i,2,n) if(!vis[i]) {
            int cur=i*i,d=1;
            rep(j,1,20) pw[j]=pw[j-1]*i;
            for(int j=i;j<=n;j+=i) {
                rep(k,1,20) if(j%pw[k]) {d=k-1;break;}
                fac[j].pb(mp(i,d)),vis[j]=1;
            }
        }
        rep(i,1,n) {
            update(root[i],root[i-1],1,n,i,1,i);
            rep(j,0,fac[i].size()-1) {
                int p=fac[i][j].xx,q=fac[i][j].yy;
                rep(k,1,20) pw[k]=(ll)pw[k-1]*p%mod;
                while(S[p].size()) {
                    int x=S[p].top().xx,r=S[p].top().yy;S[p].pop();
                    if(r<=q) update(root[i],root[i],1,n,x,pw[r],1),q-=r;
                    else {
                        update(root[i],root[i],1,n,x,pw[q],1);
                        S[p].push(mp(x,r-q));
                        q=0;
                    }
                    if(!q) break;
                }
                S[p].push(mp(i,fac[i][j].yy));
            }
        }
    }
    int Q,c[maxn],d[maxn];
    int main() {
        freopen("math.in","r",stdin);
        freopen("math.out","w",stdout);
        Q=read();
        int n=read(),k=read();
        int a=read(),b=read();P=read();
        solve(P);
        rep(i,1,Q-1) c[i]=read();
        rep(i,1,Q-1) d[i]=read();
        rep(i,1,Q) {
            int lastans;
            printf("%d
    ",lastans=calc(n,k));
            n=((ll)a*lastans+c[i])%P+1;
            k=((ll)b*lastans+d[i])%n+1;
        }
        return 0; 
    }
    T3
  • 相关阅读:
    【下一代核心技术DevOps】:(三)私有代码库阿里云Git使用
    【下一代核心技术DevOps】:(二)Rancher的应用及优点简介
    【下一代核心技术DevOps】:(一)容器服务的Rancher选型
    微服务时代之2017年五军之战:Net PHP谁先死
    Jackrabbit 文件上传下载
    eclipse闪退
    SDE For SQLServer配置说明
    RegexBuddy图文使用教程
    Eclipse闪退/打不开/无法启动/一闪而过打解决方法
    如何在window上把你的项目提交到github
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10060440.html
Copyright © 2011-2022 走看看