• 分享二合一 第二弹


    分享二合一 第二弹

    A Simple Problem

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4143

    大概题意:给一个正整数 n ,找到一个最小的正整数 x ,使存在正整数 y 满足 (y^2 = n + x^2)

    简单说一说

    题目的正解就和名字一样简单粗暴...

    首先,光看原式肯定毛都看不出来,所以移个项

    (y^2 - x^2 = n)

    再用平方差分解一下

    ((y + x)(y - x) = n)

    是不是看出来了,(y - x)(y + x)分别是 (n) 的两个因数,放在代码中就是 (i)(n / i)

    然后看看有什么值得注意的地方

    ((y + x) + (y - x) = 2y) ,为2的倍数

    ((y + x) - (y - x) = 2x) ,为2的倍数

    然后问题就解决了

    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <queue>
    #include <cmath>
    #include <map>
    using namespace std;
    const int inf=0x3f3f3f3f;
    #define ll long long
    
    map<ll,bool> m;
    
    void Init(){//开始时打表用的,不要在意
        for(int i = 1;i <= 200000;i++)
            m[(ll)i*i] = 1;
    }
    
    int main(){
        int t;
        cin>>t;
        while(t){
            t--;
            int n;
            scanf("%d",&n);
            bool flag = 1;
            int minn = inf;
            for(int i = 1;i <= sqrt(n);i++){
                int a1 = n/i,a2 = i;
                if(n%i == 0 && (a1 > a2) && (a1-a2)%2 == 0 && (a1+a2)%2 == 0){
                    flag = 0;
                    if(minn > a1-a2)
                        minn = a1-a2;
                }
            }
            if(flag){
                printf("-1
    ");
                continue;
            }
            printf("%d
    ",minn/2);
        }
        return 0;
    }
    

    Sightseeing

    链接 :http://acm.hdu.edu.cn/showproblem.php?pid=1688

    题意:给你一个有向图,可能有重边,让你求从s到t最短路的条数,如果次短路的长度比最短路的长度多1,那么在加上次短路的条数。

    其实本质上就是Dij,但是为了找次短路,我们要在松弛操作时多进行几次判断,再一个就是数组要多开一维记录状态(当然你再开一个数组也没毛病)。

    然后这道题很贴心地提示了有重边,在Dij的时候判断一下就好,当然也可以选择在建边时判断

    #include <cstdio>
    #include <queue>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <iostream>
    using namespace std;
    const int inf = 0x3f3f3f3f;
    const int maxn = 10000+10;
    #define ll long long
    
    int head[maxn],len = 0;
    struct Edge{
        int to,nex,w;
    }e[maxn<<1];
    void Add(int u,int v,int w){
        e[++len].nex = head[u];
        e[len].to = v;
        e[len].w = w;
        head[u] = len;
    }
    
    //第一维代表状态,1即为最短路,2为次短路
    //第二维代表编号,和一般的最短路一样
    ll dis[3][maxn];//记录某一状态从起点到i点距离
    int cnt[3][maxn];//记录某一状态从起点到i点路径条数
    bool vis[3][maxn];//记录某一状态下是否记录过i点
    
    struct node{
        int num,val,flag;
        node();
        node(int a,int b,int c){
            num=a,val=b,flag=c;
        }
        bool operator <(const node b)const{
            return val != b.val ? val>b.val : num>b.num;
        }
    };
    
    void Dij(int u){
        priority_queue<node> q;
        memset(dis,0x3f,sizeof dis);
        memset(vis,0,sizeof vis);
        memset(cnt,0,sizeof cnt);
        dis[1][u] = 0;
        cnt[1][u] = 1;
        q.push(node(u,0,1));
    
        while(!q.empty()){
            int num = q.top().num;
            int flag = q.top().flag;
            int val = q.top().val;
            q.pop();
            if(vis[flag][num]) continue;
            vis[flag][num] = 1;
            for(int i = head[num];i;i = e[i].nex){
                int v = e[i].to;
                int cost = e[i].w;
    
                //如果比最短路短
                if(!vis[1][v] && dis[1][v]>val+cost){
                    if(dis[1][v] != inf){//如果原先有最短路,则原来的最短路变为次短路
                        dis[2][v] = dis[1][v];
                        cnt[2][v] = cnt[1][v];
                        q.push(node(v,dis[2][v],2));
                    }   
                    dis[1][v] = val+cost;
                    cnt[1][v] = cnt[flag][num];
                    q.push(node(v,dis[1][v],1));
                }
                //如果等于最短路
                else if(!vis[1][v] && dis[1][v] == val+cost){
                    cnt[1][v] += cnt[flag][num];
                }
                //如果比最短路长但是比次短路短
                else if(!vis[2][v] && dis[2][v]>val+cost){
                    dis[2][v] = val+cost;
                    cnt[2][v] = cnt[flag][num];
                    q.push(node(v,dis[2][v],2));
                }
                //如果等于次短路
                else if(!vis[2][v] && dis[2][v] == val+cost){
                    cnt[2][v] += cnt[flag][num];
                }
            }
        }
    }
    
    int main(){
        int t,n,m;
        cin >> t;
        for(int l = 1;l <= t;l++){
            scanf("%d %d",&n,&m);
            for(int i = 1;i <= m;i++){
                int u,v,w;
                scanf("%d %d %d",&u,&v,&w);
                Add(u,v,w);
            }
            int s,f;
            scanf("%d %d",&s,&f);
            Dij(s);
            if(dis[1][f]+1 == dis[2][f])
                printf("%d
    ",cnt[1][f]+cnt[2][f]);
            else
                printf("%d
    ",cnt[1][f]);
            memset(head,0,sizeof head);//记得归零哦
            len = 0;
        }
        return 0;
    }
    
  • 相关阅读:
    【nodejs】使用Node.js实现REST Client调用REST API
    [Groovy] Groovy && JNI
    一些很实用的Maven Plugins
    秋天到了
    今天头好疼
    想起那个人的时候
    不知道标题
    生活让我懂得
    显示实现接口和实现接口
    Foreach原理
  • 原文地址:https://www.cnblogs.com/Zfio/p/12956312.html
Copyright © 2020-2023  润新知