分享二合一 第二弹
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;
}