zoukankan      html  css  js  c++  java
  • 【2018】

    D1T1.铺设道路(贪心)

    肯定要挖至少第一个坑的深度,再把后面比现在的坑的最深深度深的差值加起来,更新现在坑得最深深度(因为比现在最深深度浅的可以和之前的一起一次性处理,只用多花时间填更深的差值)。

    #include<bits/stdc++.h>
    #define ll long long
    #define ri register int 
    #define For(i,l,r) for(ri i=l;i<=r;i++)
    #define Dfor(i,r,l) for(ri i=r;i>=l;i--)
    using namespace std;
    int n,d,tmp;
    ll ans;
    inline ll read(){
        ll f=1,sum=0;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
        return f*sum;
    }
    int main(){
        n=read();
        For(i,1,n){
            d=read();
            if(d>tmp) ans+=d-tmp;
            tmp=d;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

     

    D1T2.货币系统(背包)

    瞪眼法)发现原有的货币中能且只能保留凑不出来的币值,能被凑出来的币值都不需要保留,背包可以解决。 

    #include<bits/stdc++.h>
    #define ri register int
    #define ll long long
    #define For(i,l,r) for(ri i=l;i<=r;i++)
    #define Dfor(i,r,l) for(ri i=r;i>=l;i--)
    using namespace std;
    const int M=25005;
    const int N=105;
    int T,a[N],f[M],ans,n;
    inline ll read(){
        ll f=1,sum=0;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
        return f*sum;
    }
    int main(){
        T=read();
        while(T--){
            n=read();
            For(i,1,n) a[i]=read();
            sort(a+1,a+n+1);
            f[0]=1;
            For(i,1,n){
                if(f[a[i]]) continue;
                For(j,a[i],a[n]){
                    f[j]|=f[j-a[i]]; 
                }
                ans++;
            }
            printf("%d
    ",ans);
            memset(f,0,sizeof(f));ans=0;
        }
        return 0;
    }
    View Code

    D1T3 赛道修建(菊花图+树的直径+二分答案)

    55分大众分。

    D2T1.旅行(DFS+拓扑排序+基环树)

    数据显然分为两种情况

    1. n=m-1:一棵树,vector存每个点的子点,点的编号从小到大sort一遍保证字典序最小,最后直接在树上跑dfs即可。

    2. n=m: 一棵基环树,即树上有一个环,显然环上有一条边不用跑,拓扑排序(记录出度入度,这里因为无向边所以出度入度合在一起算)标记不在环上的点,然后枚举边,如果边的两个点都在环上那么删掉这条边在树上跑一遍dfs,再比较一下字典序更新答案,然后把边加回来。

    #include<bits/stdc++.h>
    #define ri register int
    #define ll long long
    #define For(i,l,r) for(ri i=l;i<=r;i++)
    #define Dfor(i,r,l) for(ri i=r;i>=l;i--)
    using namespace std;
    const int M=5005;
    int n,m,head[M],ans[M],t,d[M],w[M][M],res[M];
    struct node{
        int u,v;
    }e[M<<1];
    vector<int>vec[M];
    bool vis[M],use[M];
    inline ll read(){
        ll f=1,sum=0;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
        return f*sum;
    }
    inline void work(){
        if(!ans[1]){
            For(i,1,n) ans[i]=res[i];
            return;
        }
        For(i,1,n){
            if(res[i]>ans[i]) return;
            if(res[i]<ans[i]){
                For(i,1,n) ans[i]=res[i];
                return;
            }
        }
    }
    inline void dfs(int x){
        vis[x]=1;res[++t]=x;
        for(ri i=0;i<vec[x].size();i++){
            int v=vec[x][i];
            if(vis[v]||!w[x][v])continue;
            dfs(v);
        }
    }
    inline void topo(){
        queue<int>q;
        For(i,1,n){
            if(d[i]==1){
                q.push(i);
                use[i]=1;
            }
        }
        while(!q.empty()){
            int u=q.front(),len=vec[u].size();
            q.pop(),use[u]=1;
            For(i,0,len-1){
                int v=vec[u][i];
                d[v]--;
                if(d[v]==1){
                    q.push(v);
                    use[v]=1;
                }
            }
        }
    }
    int main(){
        n=read(),m=read();
        For(i,1,m){
            int u=read(),v=read();
            e[i]=(node){u,v};
            d[u]++,d[v]++;
            w[u][v]=w[v][u]=1;
            vec[u].push_back(v),vec[v].push_back(u);
        }
        For(i,1,n){
            sort(vec[i].begin(),vec[i].end());
        }
        if(m==n-1){
            dfs(1);
            For(i,1,n) printf("%d ",res[i]);
            return 0;
        }
        topo();
        For(i,1,m){
            int x=e[i].u,y=e[i].v;
            if(use[x]||use[y]) continue;
            w[x][y]=w[y][x]=0;
            memset(vis,0,sizeof(vis));
            t=0;dfs(1);work();
            w[x][y]=w[y][x]=1;
        }
        For(i,1,n) printf("%d ",ans[i]);
        return 0;
    }
    View Code

    D2T2.填数游戏(打表找规律)

     数学证明显然不会也很麻烦。

    这个表其实也不是很好打,跑dfs和一个判定合法与否的函数,看看代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=100;int a[N][N],ans,no_ans,las;
    inline void ok(int x,int y,int n,int m,int cur){
        cur<<=1,cur+=a[x][y];
        if(x==n&&y==m){
            no_ans|=(cur<las);//比较大小 
            las=cur;
            return;
        }
        //下面三行也可以好好体会一下跑的顺序 
        if(y==m) ok(x+1,y,n,m,cur);
        else if(x==n) ok(x,y+1,n,m,cur);
        else ok(x,y+1,n,m,cur),ok(x+1,y,n,m,cur);
        return;
    }
    inline int can(int x,int y,int v){a[x][y]=v;no_ans=0;las=0;ok(1,1,x,y,0);return !no_ans; }
    inline int dfs(int x,int y,int n,int m){
        if(x==n+1) return ++ans;
        for(int i=0;i<=1;i++){
            if(can(x,y,i)){
                a[x][y]=i;
                //下面两行好好体会一下路径走的顺序 
                if(y==m) dfs(x+1,1,n,m);
                else dfs(x,y+1,n,m);
            }    
        }
        return 0;
    }
    inline int calc(int n,int m){ans=0;dfs(1,1,n,m);return ans;}
    int main(){
        for(int n=2;n<=7;n++){
            printf("ans(%d, %d) = %d
    ",n,n,calc(n,n));
            printf("ans(%d, %d) = %d
    ",n,n+1,calc(n,n+1));
            printf("ans(%d, %d) = %d
    ",n,n+2,calc(n,n+2));
            printf("ans(%d, %d) = %d
    ",n,n+3,calc(n,n+3));
        }
        return 0;
    }
    View Code

    然后就发现规律,

    第一个很显然,n=1即第三个和n=2和n=3看数据范围就晓得可能有特殊性质,第二(n,m和n,m-1)、五(n+1,n+1和n,n)、六(n,n+1和n,n)个比较难看,基本上就是多猜特殊性质,多输出特殊的组(如n=1,2,3..或者n,n或者n,m和m-1/m+1,n,n和n+1,n+1等等)。

     于是打出AC代码:

    #include<bits/stdc++.h>
    #define ri register int
    #define ll long long
    #define For(i,l,r) for(ri i=l;i<=r;i++)
    #define Dfor(i,r,l) for(ri i=r;i>=l;i--)
    using namespace std;
    ll f[10],n,m;
    const int p=1e9+7;
    inline ll read(){
        ll f=1,sum=0;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
        return f*sum;
    }
    inline ll ksm(ll a,ll b){
        ll ans=1;
        while(b){
            if(b&1) ans=1ll*ans*a%p;
            a=1ll*a*a%p;
            b>>=1;
        }
        return ans;
    }
    int main(){
        n=read(),m=read();
        if(n>m) swap(n,m);
        if(n==1){
            printf("%lld
    ",ksm(2,m));
            return 0;
        }
        f[2]=12,f[3]=112,f[4]=912;
        For(i,4,n-1) f[i+1]=(8ll*f[i]%p-10ll*ksm(2,i)%p+p)%p;
        if(n==m){
            printf("%lld
    ",f[n]);
            return 0;    
        }
        ll g;
        if(n==2) g=36;
        else if(n==3) g=336;
        else g=(3ll*(f[n]-ksm(2,n))%p+p)%p;
        printf("%lld
    ",(ll)g*ksm(3,m-n-1)%p);
    }
    View Code

     

  • 相关阅读:
    原型链
    原型规则总结
    使用typeof能得到的哪些类型
    eslint 规则中文注释
    两张图片互相切换
    输入框获得焦点与失去焦点、阴影效果
    vue 写table的几种方式
    vue 注意事项
    angular 接口定义封装
    @NgModule
  • 原文地址:https://www.cnblogs.com/jian-song/p/11837834.html
Copyright © 2011-2022 走看看