分享二合一 第二弹

分享二合一 第二弹

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\n");
            continue;
        }
        printf("%d\n",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\n",cnt[1][f]+cnt[2][f]);
        else
            printf("%d\n",cnt[1][f]);
        memset(head,0,sizeof head);//记得归零哦
        len = 0;
    }
    return 0;
}
posted @ 2020-05-25 13:01  zfio  阅读(168)  评论(0编辑  收藏  举报