• 2017 清北济南考前刷题Day 3 afternoon


    期望得分:100+40+100=240

    实际得分:100+40+100=240

    将每个联通块的贡献乘起来就是答案

    如果一个联通块的边数>点数 ,那么无解

    如果边数=点数,那么贡献是 2

    如果边数=点数-1,那么贡献是点数

    #include<queue>
    #include<cstdio>
    #include<iostream>
     
    using namespace std;
    
    const int mod=1e9+7;
    
    #define N 100001
    
    int front[N],to[N<<1],nxt[N<<1],tot;
    
    bool vis[N];
    
    int d[N];
    
    queue<int>q;
    
    int ans=1;
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
    void add(int u,int v)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
        d[v]++;
    }
    
    bool bfs(int s)
    {
        while(!q.empty()) q.pop();
        int p=0,e=0;
        q.push(s); vis[s]=true;
        int now; 
        while(!q.empty())
        {
            now=q.front(); q.pop();
            p++; e+=d[now];
            for(int i=front[now];i;i=nxt[i])
                if(!vis[to[i]]) vis[to[i]]=true,q.push(to[i]);
        }
        if(e>p) return false;
        if(e==p) ans=ans*2%mod;
        else ans=1ll*ans*p%mod;
        return true;
    }
    
    int main()
    {
        freopen("girl.in","r",stdin);
        freopen("girl.out","w",stdout);
        int n,m;
        read(n); read(m);
        int u,v;
        for(int i=1;i<=m;i++) 
        {
            read(u); read(v);
            add(u,v);
        }
        for(int i=1;i<=n;i++)
            if(!vis[i]) 
                if(!bfs(i)) { cout<<0; return 0; }
        cout<<ans;
        return 0;
    }
    View Code

    显然的结论:

    若一个数的K进制和-k进制相同

    那么他的k进制/-k进制的偶数位一定是0

    然后乱搞就好了

    也可以数位DP

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    
    using namespace std;
    
    typedef long long LL;
    
    LL bit[67];
    
    int a[67];
    
    int main()
    {    
        freopen("endless.in","r",stdin);
        freopen("endless.out","w",stdout);
        long long n;int k;LL ans=0;
        scanf("%I64d%d",&n,&k);
        int len=0;
        while(n) a[++len]=n%k,n/=k;
        if(!(len&1)) 
        {
            ans=pow(1LL*k,len/2);
            cout<<ans;
        }
        else 
        {
            for(int i=len;i>=1;i--)
                if(a[i])
                {
                    if(!(i&1)) { ans+=pow(1LL*k,i/2); break; }
                    ans+=1LL*a[i]*pow(1LL*k,i/2);
                    if(i==1) ans++;
                }
            cout<<ans;
        }
    }
    View Code

    40暴力 

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    
    using namespace std;
    
    int fbit[1001];
    
    int a[1001],b[1001];
    
    int pre[1001];
    
    int main()
    {
        freopen("endless.in","r",stdin);
        freopen("endless.out","w",stdout);
        int n,k;
        scanf("%d%d",&n,&k);
        fbit[0]=1;
        int la,lb; int x,ans=min(k-1,n)+1;
        for(int i=k;i<=n;i++)
        {
            la=0;
            x=i;
            while(x) a[la++]=x%k,x/=k; la--;
            x=i;
            int c=-1,now=0;
            pre[0]=k-1;
            while(1)
            {
                fbit[++now]=fbit[now-1]*c*k;
                if(!(now&1)) 
                {
                    pre[now]=pre[now-2]+(k-1)*fbit[now];
                    if(pre[now]>=x) break;
                }
                else pre[now]=pre[now-1];
            }
            lb=now;
            memset(b,0,sizeof(b));
            while(now)
            {
                if(!(now&1)) while(x>pre[now-2]) b[now]++,x-=fbit[now];
                else 
                {
                    while(x<0 && abs(x)>pre[now-1]) b[now]++,x-=fbit[now];
                    while(x>pre[now-1]) b[now]++,x+=fbit[now];
                }
                now--;
            }
            b[0]=x;
            if(la!=lb) continue;
            bool ok=true;
            for(int i=0;i<=la && ok ;i++)  if(a[i]!=b[i])  ok=false;
            if(!ok) continue;
        //    printf("%d
    ",i);
            ans++;
        }
        cout<<ans;
    }
    View Code

     考场思路:

    每次旅行一定是找当前贡献最大的叶子节点

    用线段树维护所有的叶子节点的贡献

    修改:

    每个点只会修改一次

    所以用并查集记录这个点到根节点路径上第一个没有被修改的点

    修改沿着并查集的father找上去

    对于每个要改的点,预处理出它会影响到的叶子节点,

    按dfs到的叶子节点的顺序在线段树中加点,那每个点影响到的叶子节点就是一段连续的区间

    dfs记下来,线段树区间修改即可

    其实可以不用并查集

    往上改到已经改过的点,直接break

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
     
    using namespace std;
    
    #define N 100001
    
    typedef long long LL;
    
    int n,m;
    int val[N];
    
    int front[N],nxt[N<<1],to[N<<1],tot;
    
    int F[N],fa[N],id[N];
    
    int cnt,L[N],R[N];
    
    LL w[N];
    
    LL mx[N<<2],pos[N<<2],tag[N<<2];
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
    void add(int u,int v)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
    }
    
    void init()
    {
        read(n); read(m);
        for(int i=1;i<=n;i++) read(val[i]);
        int u,v;
        for(int i=1;i<n;i++)
        {
            read(u); read(v);
            add(u,v);
        }
    } 
    
    void dfs(int x,int f,LL sum)
    {
        L[x]=cnt+1;
        F[x]=x; bool leaf=true;
        for(int i=front[x];i;i=nxt[i])
            if(to[i]!=f) leaf=false,fa[to[i]]=x,dfs(to[i],x,sum+val[to[i]]);
        if(leaf)  w[++cnt]=sum,id[cnt]=x;  
        R[x]=cnt;
    }
    
    void build(int k,int l,int r)
    {
        if(l==r) { mx[k]=w[l]; pos[k]=l; return; }
        int mid=l+r>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        mx[k]=max(mx[k<<1],mx[k<<1|1]);
        pos[k]= mx[k]==mx[k<<1] ? pos[k<<1] : pos[k<<1|1];
    }
    
    void down(int k)
    {
        mx[k<<1]-=tag[k];
        mx[k<<1|1]-=tag[k];
        tag[k<<1]+=tag[k];
        tag[k<<1|1]+=tag[k];
        tag[k]=0;
    }
    
    void change(int k,int l,int r,int opl,int opr,LL sum)
    {
        if(l>=opl && r<=opr)
        {
            mx[k]-=sum;
            tag[k]+=sum;
            return;
        }
        if(tag[k]) down(k);
        int mid=l+r>>1;
        if(opl<=mid) change(k<<1,l,mid,opl,opr,sum);
        if(opr>mid) change(k<<1|1,mid+1,r,opl,opr,sum);
        mx[k]=max(mx[k<<1],mx[k<<1|1]);
        pos[k]=mx[k]==mx[k<<1] ? pos[k<<1] : pos[k<<1|1];
    }
    
    
    int find(int i) { return F[i]==i ? i : F[i]=find(F[i]); }
    
    void solve()
    {
        int p; LL ans=0;
        while(m--)
        {
            p=id[pos[1]]; // 第pos个叶子节点 
            ans+=mx[1];
            while(p)
            {
                change(1,1,cnt,L[p],R[p],val[p]);
                F[p]=find(F[fa[p]]);
                p=F[p];
            }
        }
        cout<<ans;
    }
    
    int main()
    {
        freopen("tour.in","r",stdin);
        freopen("tour.out","w",stdout);
        init();
        dfs(1,0,val[1]);
        build(1,1,cnt);
        solve();
    }
    View Code
  • 相关阅读:
    Asp.NET 4.0 ajax实例DataView 模板编程1
    ASP.NET 4.0 Ajax 实例DataView模板编程 DEMO 下载
    部分东北话、北京话
    .NET 培训课程解析(一)
    ASP.NET 4.0 Ajax 实例DataView模板编程2
    ASP.NET Web Game 架构设计1服务器基本结构
    ASP.NET Web Game 构架设计2数据库设计
    TFS2008 基本安装
    Linux上Oracle 11g安装步骤图解
    plsql developer远程连接oracle数据库
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7755369.html
Copyright © 2020-2023  润新知