20190810

AGC014 E Blue and Red Tree

link

$solution:$

Consider the nature of the topic can be found in the mangrove tree blue certainly have to pay, and will cut off the last time.

So consider the reverse process, how to blue from mangrove trees.

The last case out promotion, and each time have had a similar intersection.

Consider how to maintain, through the combined $ set $ heuristic and disjoint-set time complexity $ O (n \ log ^ 2 n) $.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int MAXN=200001;
map<pair<int,int> ,int> M;
set<int> s[MAXN];
queue<pair<int,int> > que;
void add(int u,int v){
    s[u].insert(v),s[v].insert(u);
    if(u>v) swap(u,v);
    M[make_pair(u,v)]++;
    if(M[make_pair(u,v)]==2) que.push(make_pair(u,v));
    return; 
}
void del(int u,int v){
    s[u].erase(v),s[v].erase(u);
    if(u>v) swap(u,v);
    M.erase(make_pair(u,v));
}
set<int>::iterator it,it1;
int n,f[MAXN];
int find(int x){if(f[x]==x) return x;return f[x]=find(f[x]);}
bool solve(){
    int tot=0;
    for(int i=1;i<=n;i++) f[i]=i;
    while(!que.empty()){
        int u=que.front().first,v=que.front().second;que.pop();
        tot++;
        u=find(u),v=find(v);
        if(s[u].size()<s[v].size()) swap(u,v);
        del(u,v);
        f[v]=u;
        for(it=s[v].begin();it!=s[v].end();){
            it1=it;it++;
            int end=*it1;end=find(end);
            del(v,end),add(u,end);
        }
    }
    return tot==(n-1);
}
int main(){
    freopen("tree.in","r",stdin);
    freopen("tree.out","w",stdout);
    n=read();
    for(int i=1;i<n;i++) add(read(),read());
    for(int i=1;i<n;i++) add(read(),read());
    if(solve()){printf("YES\n");return 0;}
    printf("NO\n");return 0;
}
View Code

 

[2017 Team work since the topic # 119] the mode MAX

$solution:$

The mode is certainly to enumerate, consider violence to obtain the number for the number of the congregation $ x $.

Set $ ​​A_i $ $ a_x = i $ represents the number of occurrences, $ B_i $ is all about.

The $ Ans_i = \ sum min \ {A_j, B_ {ij} \} $. This equation can be much like the convolution formula, but can not be calculated $ min $ operation.

However, expression can be disassembled to do, then $$ Ans_i = \ sum_ {x = 1} ^ {n (k)} \ sum_ {j = 0} ^ i [A_j \ geq x] \ times [B_ {ij } \ geq x] \\ = \ sum_ {x = 1} ^ n \ sum_ {j = 0} ^ i c_j \ times d_ {ij} $$

Time complexity $ O (k \ times n \ log n) $.

But at the moment $ k $ and $ n $ of the same order. Consideration found by simply appear to $ k $ A $ times not exceeding $ $ \ dfrac {n} {k} $ a, can be provided by $ k $, $ $ NTT violence simultaneously processing two different situations.

Time complexity $ O (k \ times n \ log n + \ dfrac {n ^ 2} {k ^ 2}) $, $ 10 $ $ k $ when taken in optimal.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
#define mod 998244353
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int MAXN=600001;
namespace Poly{
    int f[MAXN],g[MAXN],flip[MAXN];
    inline int ksm(int a,int b){
        int ans=1;
        while(b){
            if(b&1) ans*=a,ans%=mod;
            a*=a,a%=mod;
            b>>=1;
        }return ans;
    }
    inline int Get(int lim){
        int len=1;while(len<=lim) len<<=1;
        for(register int i=0;i<len;i++) flip[i]=((flip[i>>1]>>1)|(i&1?len>>1:0));
        return len;
    }
    inline void NTT(int *f,int lim,int opt){
        for(register int i=0;i<lim;i++) if(i<flip[i]) swap(f[i],f[flip[i]]);
        for(register int p=2;p<=lim;p<<=1){
            int len=p>>1,buf=ksm(3,(mod-1)/p);
            if(opt==-1) buf=ksm(buf,mod-2);
            for(register int be=0;be<lim;be+=p){
                int tmp=1;
                for(register int l=be;l<be+len;l++){
                    int t=f[l+len]*tmp;t%=mod;
                    f[l+len]=(f[l]-t+mod)%mod,f[l]=(f[l]+t)%mod;
                    tmp*=buf,tmp%=mod;
                }
            }
        }
        if(opt==-1){
            int Inv=ksm(lim,mod-2);
            for(register int i=0;i<lim;i++) f[i]*=Inv,f[i]%=mod;
        }return;
    }
}
int n,Maxn,a[MAXN],b[MAXN],A[MAXN],B[MAXN],f[MAXN],g[MAXN],ans[MAXN],staa[MAXN],stab[MAXN];
signed main(){
    freopen("max.in","r",stdin);
    freopen("max.out","w",stdout); 
    n=read();
    for(int i=1;i<=n;i++) a[i]=read(),A[a[i]]++;
    for(int i=1;i<=n;i++) b[i]=read(),B[b[i]]++;
    int lim=Poly::Get(200000);
    for(register int i=1;i<=10;i++){
        memset(f,0,sizeof(f)),memset(g,0,sizeof(g));
        for(register int j=1;j<=100000;j++) f[j]=(A[j]>=i),g[j]=(B[j]>=i);
        Poly::NTT(f,lim,1),Poly::NTT(g,lim,1);
        for(register int j=0;j<lim;j++) f[j]*=g[j],f[j]%=mod;
        Poly::NTT(f,lim,-1);
        for(int j=0;j<lim;j++) ans[j]+=f[j];
    }
    for(register int i=1;i<=100000;i++){
        if(A[i]>10) staa[++staa[0]]=i;
        if(B[i]>10) stab[++stab[0]]=i;
    }
    for(register int i=1;i<=staa[0];i++)
        for(int j=1;j<=stab[0];j++) ans[staa[i]+stab[j]]+=min(A[staa[i]],B[stab[j]])-10;
    for(register int i=1;i<=200000;i++) Maxn=max(Maxn,ans[i]);
    printf("%lld\n",Maxn);return 0;
}
View Code

 

 AGC005 D ~K Perm Counting

link

$solution:$

Consider inclusion and exclusion, provided G_i $ $ $ I $ indicates that at least one point satisfies $ | a_j-j | = k $ the number of programs.

则 $Ans=\sum_i (-1)^i\times g_i\times (n-i)!$ 。

Consider the establishment of a bipartite graph, the left index is, the right is the weight, if the edge $ (u, v) $, $ U as the index can not be selected from $ $ v $.

The bipartite graph simply pull out $ dp $ can.

Time complexity $ O (n ^ 2) $.

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
#define mod 924844033
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int MAXN=4001;
int fac[MAXN],f[MAXN][MAXN][2],n,k,sta[MAXN],col[MAXN];
int Mod(int x){return ((x%mod)+mod)%mod;}
signed main(){
    freopen("count.in","r",stdin);
    freopen("count.out","w",stdout);
    n=read(),k=read();fac[0]=1;
    for(int i=1;i<=n;i++) fac[i]=(fac[i-1]*i)%mod;
    for(int i=1;i<=k;i++){
        col[0]++;
        for(int j=i;j<=n;j+=k) sta[++sta[0]]=j,col[sta[0]]=col[0];
        col[0]++;
        for(int j=i;j<=n;j+=k) sta[++sta[0]]=j,col[sta[0]]=col[0]; 
    }
    f[1][0][0]=1;
    for(int i=2;i<=sta[0];i++){
        for(int j=0;j<=n;j++){
            f[i][j][0]=f[i-1][j][0]+f[i-1][j][1];f[i][j][0]=Mod(f[i][j][0]);
            if(j!=0&&col[i]==col[i-1]) f[i][j][1]=f[i-1][j-1][0],f[i][j][1]%=mod;
        }
    }
    int Ans=0,pw=1;
    for(int i=0;i<=n;i++){
        Ans+=pw*fac[n-i]*((f[sta[0]][i][0]+f[sta[0]][i][1])%mod),Ans=Mod(Ans),pw*=-1;
    }
    printf("%lld\n",Ans);return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/si-rui-yang/p/11332482.html