Comet OJ - Contest #2

A

code:

#include <cstdio> 
#include <algorithm>    
#define N 1000000 
#define ll long long 
#define setIO(s) freopen(s".in","r",stdin)   
using namespace std; 
ll f[N],g[N];      
int main() 
{    
    // setIO("input");  
    int i,j;     
    f[1]=1,f[2]=1,g[2]=2;        
    ll x;  
    scanf("%lld",&x);    
    if(x<=2) { printf("%lld\n",x+1);      return 0; }    
    for(i=3;;++i) 
    {
        f[i]=g[i-1]/2;      
        g[i]=g[i-1]+f[i];      
        if(g[i]>x) 
        {
            printf("%d\n",i); 
            return 0;  
        } 
    }
    return 0;
}

  

B

推式子发现是二次函数的形式,套用二次函数公式好了. 

code: 

#include <cstdio> 
#include <algorithm> 
#include <cstring> 
#include <cmath>     
#define ll long long 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std; 
int main() 
{ 
    // setIO("input");      
    int i,j;   
    double l,r,L,R;  
    scanf("%lf%lf%lf%lf",&l,&r,&L,&R);       
    double q=(L+R)*0.5;      
    double sl=(l+q)*0.5;      
    sl=max(l,min(sl,r));                                  
    printf("%.4f\n",max(0.0000,(double)(sl-l)/(r-l)*(q-sl)));   
    return 0;    
}

  

C

感觉这个比 B 简单啊,直接枚举就好了. 

code: 

#include <cstdio>  
#include <map> 
#include <vector>   
#include <set>   
#include <cstring> 
#include <algorithm>   
#define ll long long 
#define mod 998244353   
#define N 100006 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;  
int fac[N],inv[N];  
int qpow(int x,ll y)  
{
    int tmp=1;   
    for(;y;y>>=1,x=(ll)x*x%mod) 
        if(y&1) tmp=(ll)tmp*x%mod;  
    return tmp;  
} 
int INV(int x) { return qpow(x,mod-2); }     
void init() 
{
    fac[0]=inv[0]=1;
    int i,j;    
    for(i=1;i<N;++i) fac[i]=(ll)fac[i-1]*i%mod,inv[i]=INV(fac[i]);   
}
int C(int x,int y) 
{
    if(x<0||y<0||x<y) return 0;   
    return (ll)fac[x]*inv[y]%mod*inv[x-y]%mod;  
}
int main() 
{
    // setIO("input");        
    init();  
    int n,x,y,ans=0,i,j,det;          
    scanf("%d%d%d",&n,&x,&y);   
    det=(ll)x*INV(y)%mod;               
    for(i=1;i<=n;++i) 
    { 
        int tp=(ll)C(n,i)*qpow(det,1ll*i*(i-1)/2)%mod;    
        (ans+=(ll)C(n,i)*qpow(det,(ll)i*(i-1)/2)%mod)%=mod;             
    }
    printf("%d\n",(ans+1)%mod);  
    return 0;  
}         

  

D

枚举中心点,容斥原理算一算 

code: 

#include <bits/stdc++.h>  
#define N 4010 
#define ll long long 
#define mod 998244353    
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;  
int edges,now,n;  
int hd[N<<1],to[N<<2],nex[N<<2],cnt[N<<1][N],sum[N],bin[N],ans[N];      
void add(int u,int v) 
{
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;    
}
void dfs(int u,int ff,int d) 
{
    if(u<=n) ++sum[d], ++cnt[now][d];        
    for(int i=hd[u];i;i=nex[i]) if(to[i]!=ff) dfs(to[i], u, d+1); 
}
int main() 
{  
    // setIO("input");  
    int i,j;  
    scanf("%d",&n);   
    bin[0]=1; 
    for(i=1;i<=n;++i) bin[i]=bin[i-1]*2%mod; 
    for(i=1;i<n;++i) 
    {
        int u,v; 
        scanf("%d%d",&u,&v);    
        add(u,i+n),add(i+n,u);
        add(i+n,v),add(v,i+n);           
    }  
    for(i=1;i<=2*n;++i) 
    {
        now=0;   
        for(j=hd[i];j;j=nex[j]) ++now, dfs(to[j],i,1);         
        int re=(i<=n);     
        for(j=1;j<n;++j) 
        {
            int mdl=bin[sum[j]]-1;   
            for(int k=1;k<=now;++k) 
            {
                (mdl+=mod-bin[cnt[k][j]]+1)%=mod;   
            }    
            (ans[j]+=(ll)mdl*bin[re]%mod)%=mod;    
            re+=sum[j];   
        }
        memset(sum,0,sizeof sum);   
        for(j=1;j<=now;++j) memset(cnt[j], 0, sizeof cnt[j]);    
    }
    for(i=1;i<n;++i) 
        printf("%d\n",(ans[i]+mod)%mod);    
    return 0;   
}

  

E

我们发现图形是一个基环数森林.   

如果是树形结构的话十分方便.   

而我们可以将问题简化为如何处理环.    

显然,我们要枚举起点,并将起点出发的边断开,然后维护一圈 $ans_{i}=A_{i}+B_{i} \times ans_{i-1}$.   

这个满足结合律,用线段树维护即可. 

code: 

#include <cstdio> 
#include <algorithm>        
#include <cstring>        
#include <vector> 
#include <map>   
#include <queue>   
#define ll long long    
#define N 200008   
#define mod 998244353  
#define setIO(s) freopen(s".in","r",stdin)  
using namespace std;    
int A[N],B[N],ans[N];      
int qpow(int x,int y) 
{
    int tmp=1; 
    for(;y;y>>=1,x=(ll)x*x%mod) 
        if(y&1) tmp=(ll)tmp*x%mod; 
    return tmp;   
}
int INV(int x) { return qpow(x,mod-2); } 
namespace seg
{     
    #define lson now<<1 
    #define rson now<<1|1    
    struct node 
    {
        int a,b;          
        node() { a=b=0; }
        node operator+(const node &t) const 
        {    
            node c;   
            c.a=(ll)(t.a+(ll)t.b*a%mod)%mod;   
            c.b=(ll)t.b*b%mod;    
            return c;       
        }         
    }s[N<<2];   
    void build(int l,int r,int now) 
    {
        if(l==r) 
        {       
            s[now].a=A[l];  
            s[now].b=B[l];   
            return;  
        }  
        int mid=(l+r)>>1;    
        build(l,mid,lson),build(mid+1,r,rson);    
        s[now]=s[lson]+s[rson]; 
    } 
    node query(int l,int r,int now,int L,int R) 
    {
        if(l>=L&&r<=R) return s[now];    
        int mid=(l+r)>>1;  
        if(L<=mid&&R>mid) return query(l,mid,lson,L,R)+query(mid+1,r,rson,L,R); 
        else if(L<=mid) return query(l,mid,lson,L,R); 
        else return query(mid+1,r,rson,L,R);    
    }       
    #undef lson 
    #undef rson  
};   
int n;               
int deg[N],p[N],go[N],seq[N],id[N],s[N];                        
queue<int>q;                                        
void solve_tree() 
{    
    int i,j;      
    for(i=1;i<=n;++i) if(!deg[i]) q.push(i);    
    while(!q.empty()) 
    {
        int u=q.front();q.pop();          
        int v=go[u];    
        --deg[v];    
        p[v]=(ll)(p[v]+(ll)(1-p[v]+mod)*s[u]%mod*p[u]%mod)%mod;    
        if(deg[v]==0) q.push(v);      
    }
}
void solve_circle(int x) 
{          
    int i,j;   
    int t=go[x],top=0;      
    seq[++top]=x;                       
    while(t!=x) seq[++top]=t,t=go[t];    
    for(i=1;i<=top;++i) seq[top+i]=seq[i];                                  
    for(i=1;i<=top;++i) id[seq[i]]=i,deg[seq[i]]=0;       
    for(i=2;i<=(top<<1);++i) 
    {
        A[i]=p[seq[i]];          
        B[i]=(ll)(1-p[seq[i]]+mod)*s[seq[i-1]]%mod;            
    }
    A[1]=A[top+1],B[1]=B[top+1];    
    seg::build(1,top<<1,1);                            
    for(i=1;i<=top;++i) 
    {
        int u=seq[i];           
        seg::node an=seg::query(1,top<<1,1,i+2,i+top);                          
        ans[u]=(ll)((ll)an.b*p[seq[i+1]]%mod+an.a)%mod;    
    }
}
int main() 
{ 
    // setIO("input");         
    int i,j; 
    scanf("%d",&n);  
    for(i=1;i<=n;++i) 
    { 
        int x,y;   
        scanf("%d%d",&x,&y);        
        p[i]=(ll)x*INV(y)%mod;   
    }
    for(i=1;i<=n;++i) scanf("%d",&go[i]),++deg[go[i]];      
    for(i=1;i<=n;++i) 
    {
        int x,y;   
        scanf("%d%d",&x,&y);     
        s[i]=(ll)x*INV(y)%mod;   
    }
    solve_tree();      
    for(i=1;i<=n;++i)  if(!deg[i]) ans[i]=p[i];  
    for(i=1;i<=n;++i) 
    {
        if(deg[i]) solve_circle(i); 
        printf("%d ",ans[i]);   
    }
    return 0;   
}

  

posted @ 2020-02-14 22:31  EM-LGH  阅读(137)  评论(0编辑  收藏  举报