• 18.10.18队测


    T1 : 题意简述 : 三维偏序问题,每一维都是一个排列,求满足((a_i<a_j,b_i<b_j,c_i<c_j))的有序二元组个数。

    其中:(nleq2e6).

    这题的题目名字就叫cdq。。。显然我们不能cdq,时间复杂度不允许。

    由于是排列,没有重复的数,所以可以容斥。先按((a,b),(a,c),(b,c))做二维偏序,设答案为(x,y,z),那么不合法的肯定只会在任意一种二维偏序中出现一次,所以总答案为

    [ans=frac{1}{2}(x+y+z-inom{n}{2}) ]

    #include<bits/stdc++.h>
    #pragma GCC optimize(3)
    #define ll long long
    using namespace std;
    void read(int &x){
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-f;
        for(;isdigit(ch);ch=getchar())x=(x<<1)+(x<<3)+ch-'0';x*=f;
    }
    #define maxn 2000050
    #define write(x) printf("%lld
    ",x)
    int n,k,tot;
    struct data{int x,y,z;}s[maxn],p[maxn];
    struct binary_index_tree{
        int tree[maxn];void clear() {memset(tree,0,sizeof tree);}
        void modify(int x,int v){for(int i=x;i<=n;i+=i&-i)tree[i]+=v;}
        int query(int x,int ans=0){for(int i=x;i;i-=i&-i)ans+=tree[i];return ans;}
    }T;
    namespace make {
        const int N = 2e6+5;
        unsigned int SA,SB,SC;int a[N],b[N],c[N];
        unsigned int rd(){
            SA^=SA<<16;SA^=SA>>5;SA^=SA<<1;
            unsigned int t=SA;SA=SB;SB=SC;SC^=t^SA;return SC;
        }
        void gen(int *P){
            for (int i=1;i<=n;++i) P[i]=i;
            for (int i=1;i<=n;++i) swap(P[i],P[1+rd()%n]);
        }
        void get(){
            scanf("%d%u%u%u",&n,&SA,&SB,&SC);
            gen(a);gen(b);gen(c);
            for(int i=1;i<=n;i++) s[i].x=a[i],s[i].y=b[i],s[i].z=c[i];
        }
    }
    int cmp_x(data x,data y) {return x.x<y.x;}
    int cmp_y(data x,data y) {return x.y<y.y;}
    int main(){
        make :: get();sort(s+1,s+n+1,cmp_x);long long ans=0;
        for(int i=1;i<=n;i++) ans+=T.query(s[i].y),T.modify(s[i].y,1);T.clear();
        for(int i=1;i<=n;i++) ans+=T.query(s[i].z),T.modify(s[i].z,1);T.clear();
        sort(s+1,s+n+1,cmp_y);for(int i=1;i<=n;i++) ans+=T.query(s[i].z),T.modify(s[i].z,1);
        write((ans-1ll*n*(n-1)/2)/2);
        return 0;
    }
    
      
    

    T2过于毒瘤,不会。。。。。

    T3 : 题意简述 : 给出一颗树,有(q)个询问,每次询问给出一条链((u,v)),要找出(k)个点对,使得两两点对的公共路径为((u,v)),对于每次询问会要求可否选重复的点,求方案数。

    (f[u][k])(u)的子树中选(k)个点,且每个(u)的儿子的子树中最多只能有一个点的方案数,考虑已经算完了(u)(1)~ (~n-1) 的儿子对它的贡献,现在要新增一个点,显然可以得到转移(f[u][k]+=f[u][k-1]*sz[e[i].to]).要逆序转移。

    对于(u,v)没有祖先关系,直接拿(f)统计就好了。

    否则,设(u)(v)的祖先,我们就以(v)的方向为根,对与(u)类似与(f)反向处理出新的(f)统计答案,具体的细节看代码吧。。

    #include<bits/stdc++.h>
    #pragma GCC optimize(3)
    #define int long long
    using namespace std;
    void read(int &x){
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-f;
        for(;isdigit(ch);ch=getchar())x=(x<<1)+(x<<3)+ch-'0';x*=f;
    }
    #define write(x) printf("%lld
    ",x)
    #define mod 998244353
    #define maxn 100050
    int n,k,tot,q,head[maxn],sz[maxn],f[maxn][501],dfn[maxn],dfn_cnt,fac[maxn],ifac[maxn],g[501],Fa[maxn];
    struct edge{int to,nxt;}e[maxn<<1];
    int qpow(int a,int x,int res=1) {for(;x;x>>=1,a=a*a%mod) if(x&1) res=res*a%mod;return res;}
    void ins(int u,int v) {e[++tot].to=v,e[tot].nxt=head[u],head[u]=tot;}
    void dfs(int x,int fa) {
        dfn[x]=++dfn_cnt;sz[x]=1;f[x][0]=1;int top=0;Fa[x]=fa;
        for(int i=head[x];i;i=e[i].nxt)
            if(e[i].to!=fa) {
                dfs(e[i].to,x);sz[x]+=sz[e[i].to];
                for(int j=top;~j;j--) (f[x][j+1]+=sz[e[i].to]*f[x][j])%=mod;top++;
            }
    }
    void solve(int u,int v,int k) {
        int y=0;memcpy(g,f[u],sizeof g);
        for(int i=head[u];i;i=e[i].nxt) if(e[i].to!=Fa[u]) if(dfn[e[i].to]+sz[e[i].to]-1>=dfn[v]&&dfn[e[i].to]<=dfn[v]) {y=e[i].to;break;}//write(y);
        for(int i=1;i<=k;i++) g[i]=((g[i]-g[i-1]*sz[y])%mod+mod)%mod;
        for(int i=k;i;i--) g[i]=(g[i]+g[i-1]*(n-sz[u]))%mod;
    }
    signed main() {
        read(n),read(q);int x,y;
        for(int i=1;i<n;i++) read(x),read(y),ins(x,y),ins(y,x);
        fac[0]=ifac[0]=1;for(int i=1;i<=500;i++) fac[i]=fac[i-1]*i%mod;
        ifac[500]=qpow(fac[500],mod-2);for(int i=500-1;i;i--) ifac[i]=ifac[i+1]*(i+1)%mod;
        dfs(1,0);
        while(q--) {
            int k,op,u,v;read(u),read(v),read(k),read(op);
            if(dfn[u]>dfn[v]) swap(u,v);
            if(op==1) {
                if(dfn[v]>=dfn[u]+sz[u]) write((f[u][k]+f[u][k-1])*(f[v][k]+f[v][k-1])%mod*fac[k]%mod*fac[k]%mod);//,puts("A");
                else {
                    int ans=(f[v][k]+f[v][k-1])*fac[k]%mod;
                    solve(u,v,k);ans=ans*(g[k]+g[k-1])%mod*fac[k]%mod;write(ans);//puts("B");
                }
            } else {
                if(dfn[v]>=dfn[u]+sz[u]) {
                    int ans0=0,ans1=0;
                    for(int i=0;i<=k;i++) ans0=(ans0+f[u][i]*fac[k]%mod*ifac[k-i]%mod)%mod;
                    for(int i=0;i<=k;i++) ans1=(ans1+f[v][i]*fac[k]%mod*ifac[k-i]%mod)%mod;
                    write(ans0*ans1%mod);//puts("C");
                } else {
                    int ans0=0,ans1=0;
                    for(int i=0;i<=k;i++) ans1=(ans1+f[v][i]*fac[k]%mod*ifac[k-i]%mod)%mod;
                    solve(u,v,k);for(int i=0;i<=k;i++) ans0=(ans0+g[i]*fac[k]%mod*ifac[k-i]%mod)%mod;
                    write(ans0*ans1%mod);//puts("D");
                }
            }
        }
        return 0;
    }
     
    
  • 相关阅读:
    HTML与CSS(图解1):标志
    CSS :focus 伪类
    JAVA: java产生随机数的几种方式
    HTML:文件类型
    JAVA:Random类 (java.util)
    电脑知识:ping
    cih病毒源代码
    JAVA:控制台输入问题
    HTML:校验器
    第二十三模板 6类模板的定义 简单
  • 原文地址:https://www.cnblogs.com/hbyer/p/9815216.html
Copyright © 2020-2023  润新知