zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    03-架构设计的目的
    02-架构设计的历史背景
    01-架构到底是指什么
    python 基础 1.5 python数据类型(四)--字典
    python 基础 1.5 python数据类型(三)--元组常用方法示例
    python 基础 1.5 python数据类型(三)--元组
    python 基础 1.5 python数据类型(二)--列表常用方法示例
    python 基础 1.5 数据类型(二)--列表
    python 基础 1.5 python 数据类型(一)--整型 浮点型 布尔型及字符串和常用方法
    python 基础 1.4 python运算符
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7755369.html
Copyright © 2011-2022 走看看