2019 GDUT Winter Training IV ( 图论基础和基础数论 ) 题解

      2019 GDUT Winter Training IV ( 图论基础和基础数论 ) 题解

                                                 A题

题面:

                                     A - Invitation Cards

In the age of television, not many people attend theater performances. Antique Comedians of Malidinesia are aware of this fact. They want to propagate theater and, most of all, Antique Comedies. They have printed invitation cards with all the necessary information and with the programme. A lot of students were hired to distribute these invitations among the people. Each student volunteer has assigned exactly one bus stop and he or she stays there the whole day and gives invitation to people travelling by bus. A special course was taken where students learned how to influence people and what is the difference between influencing and robbery. 

The transport system is very special: all lines are unidirectional and connect exactly two stops. Buses leave the originating stop with passangers each half an hour. After reaching the destination stop they return empty to the originating stop, where they wait until the next full half an hour, e.g. X:00 or X:30, where 'X' denotes the hour. The fee for transport between two stops is given by special tables and is payable on the spot. The lines are planned in such a way, that each round trip (i.e. a journey starting and finishing at the same stop) passes through a Central Checkpoint Stop (CCS) where each passenger has to pass a thorough check including body scan. 

All the ACM student members leave the CCS each morning. Each volunteer is to move to one predetermined stop to invite passengers. There are as many volunteers as stops. At the end of the day, all students travel back to CCS. You are to write a computer program that helps ACM to minimize the amount of money to pay every day for the transport of their employees. 

Input

The input consists of N cases. The first line of the input contains only positive integer N. Then follow the cases. Each case begins with a line containing exactly two integers P and Q, 1 <= P,Q <= 1000000. P is the number of stops including CCS and Q the number of bus lines. Then there are Q lines, each describing one bus line. Each of the lines contains exactly three numbers - the originating stop, the destination stop and the price. The CCS is designated by number 1. Prices are positive integers the sum of which is smaller than 1000000000. You can also assume it is always possible to get from any stop to any other stop.

Output

For each case, print one line containing the minimum amount of money to be paid each day by ACM for the travel costs of its volunteers.

Sample Input

2
2 2
1 2 13
2 1 33
4 6
1 2 10
2 1 60
1 3 20
3 4 10
2 4 5
4 1 50

Sample Output

46
210

题面描述:

            这个题目的大概意思是,所有的ACM会员都要从起点到预定的站点去邀请乘客,然后在一天结束后,所有的ACM会员都会回到起点,题目中的起点默认是第一个站点,这个题目让我们求的是这些ACM会员从起点去到其他站点一来一回最少的花费是多少。(这个题目给的数据从某个站点到另一个站点是单向的)

题目分析:

            我们分为两步,第一步是求从第一个站到达其他站的最短路径,这个过程我们可以用Dijkstra算法或者spfa来算出来。

            第二步,我们是要求从其他所有站点回到第一个站点的最短路径,如果我们枚举全部站点到达第一个站点的最短路径,很显然会超时,因此我们构建原本构建的图的反向图,然后再求第一个站点到达其他站点的最短路径。

            最后对于每个站点,我们把两次求出来的最短路径全部加起来即为答案。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int MaxP=1e6+5;
const int MaxQ=1e6+5;
struct Bus
{
	int s,t,price;
};
struct node
{
	int t,price;
};
Bus bus[MaxQ];
node edge[MaxQ];
ll cost[MaxP],costt[MaxP];
priority_queue  q;
int tot,P;
int nextt[MaxP],first[MaxP];
bool operator < (node a,node b)
{
	return a.price>b.price;
}
void addedge(int a,int b,int price)
{
	edge[++tot].t=b;
	edge[tot].price=price;
	nextt[tot]=first[a];
	first[a]=tot;
}
void Dijkstra()
{
	for (reg int i=1;i<=P;i++) cost[i]=INF; 
	node temp;
	temp.t=1;temp.price=0;
	q.push(temp);cost[1]=0;
	while (!q.empty())
	{
		temp=q.top();q.pop();
		for (reg int i=first[temp.t];i!=-1;i=nextt[i])
		if (cost[temp.t]+edge[i].price

 

                                                 B题

题面:

                                           B - ROADS

N cities named with numbers 1 ... N are connected with one-way roads. Each road has two parameters associated with it : the road length and the toll that needs to be paid for the road (expressed in the number of coins). 
Bob and Alice used to live in the city 1. After noticing that Alice was cheating in the card game they liked to play, Bob broke up with her and decided to move away - to the city N. He wants to get there as quickly as possible, but he is short on cash. 

We want to help Bob to find the shortest path from the city 1 to the city N that he can afford with the amount of money he has. 

Input

The first line of the input contains the integer K, 0 <= K <= 10000, maximum number of coins that Bob can spend on his way. 
The second line contains the integer N, 2 <= N <= 100, the total number of cities. 

The third line contains the integer R, 1 <= R <= 10000, the total number of roads. 

Each of the following R lines describes one road by specifying integers S, D, L and T separated by single blank characters : 

  • S is the source city, 1 <= S <= N 
  • D is the destination city, 1 <= D <= N 
  • L is the road length, 1 <= L <= 100 
  • T is the toll (expressed in the number of coins), 0 <= T <=100


Notice that different roads may have the same source and destination cities.

Output

The first and the only line of the output should contain the total length of the shortest path from the city 1 to the city N whose total toll is less than or equal K coins. 
If such path does not exist, only number -1 should be written to the output. 

Sample Input

5
6
7
1 2 2 3
2 4 3 3
3 4 2 4
1 3 4 1
4 6 2 1
3 5 2 0
5 4 3 2

Sample Output

11

题面描述:

             这个题目求的是从第一个城市到达第n个城市的最短路径,并且这个最短路径的总花费不能超过K。

题目分析:

            这个题目的求解就是要在Dijkstra算法求解最短路径的时候加上判别第一个城市到达当前城市的总花费是否超过K,然后最后输出满足条件的从第一个城市到达第n个城市的最短路径即可。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int MaxN=105;
const int MaxR=1e5+5;
const int MaxK=1e5+5;
struct node
{
	int t,len,toll;
};
int N,K,tot;
int nextt[MaxR],first[MaxN];
node edge[MaxR];
priority_queue  q;
bool operator < (node a,node b)
{
	return a.len>b.len;
}
void addedge(int a,int b,int len,int toll)
{
	edge[++tot].t=b;
	edge[tot].len=len;
	edge[tot].toll=toll;
	nextt[tot]=first[a];
	first[a]=tot;
}
int Dijkstra()
{
	node temp;
	temp.t=1;temp.len=0;temp.toll=0;
	q.push(temp);
	while (!q.empty())
	{
		temp=q.top();q.pop();
		if (temp.t==N) return temp.len;
		for (reg int i=first[temp.t];i!=-1;i=nextt[i])
		if (temp.toll+edge[i].toll<=K)
		{
			node tt;
			tt.t=edge[i].t;tt.len=temp.len+edge[i].len;tt.toll=temp.toll+edge[i].toll;
			q.push(tt);
		}
	}
}
int main()
{
	int R;
	tot=0;
	memset(first,-1,sizeof(first));
	scanf("%d%d%d",&K,&N,&R);
	for (reg int i=1;i<=R;i++)
	{
		int S,D,L,T;
		scanf("%d%d%d%d",&S,&D,&L,&T);
		addedge(S,D,L,T); 
	}
	printf("%d\n",Dijkstra());
	return 0;
}

 

                                                 C题

题面:

                                       C - Popular Cows

Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <= M <= 50,000) ordered pairs of the form (A, B) that tell you that cow A thinks that cow B is popular. Since popularity is transitive, if A thinks B is popular and B thinks C is popular, then A will also think that C is 
popular, even if this is not explicitly specified by an ordered pair in the input. Your task is to compute the number of cows that are considered popular by every other cow. 

Input

* Line 1: Two space-separated integers, N and M 

* Lines 2..1+M: Two space-separated numbers A and B, meaning that A thinks B is popular. 

Output

* Line 1: A single integer that is the number of cows who are considered popular by every other cow. 

Sample Input

3 3
1 2
2 1
2 3

Sample Output

1

Hint

Cow 3 is the only cow of high popularity. 

题面描述:

            这个题目讲述的是,如果奶牛A认为奶牛B很受关注,然后奶牛B也认为奶牛C很受关注,因此便得出奶牛A认为奶牛C很受关注(即奶牛之间的受关注是具有传递性的),然后就是要求出n头奶牛当中有多少头奶牛被其他n-1头奶牛认为很受关注。

题目分析:

             这个题目我们很容易想到,如果两头奶牛之间互相认为对方很受关注,那么我们就可以把这两头奶牛看成是一个整体,其实m头奶牛也一样,因此我们就要把这n头奶牛当中的强连通分量进行缩点(这里可以用Tarjan算法或者Kosaraju算法),然后再判断经过缩点后的每个点的出度是否为0,如果出度为0的点我们记录一下,出度为0的点的个数如果为1的话,就证明存在一个点当中的所有奶牛都被其他奶牛认为很受欢迎,我们把这个点里面的奶牛数计算出来即可(出度为0的点的个数不为1的话,就证明不存在一头奶牛被其他奶牛认为很受欢迎,这是因为这些出度为0的点之间并没有存在一方认为另一方很受欢迎的情况,所以不满足题目条件)。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int MaxN=1e4+5;
const int MaxM=5e4+5;
int N,tot,tt,ans,timee;
int dfn[MaxN],cnt[MaxN],num[MaxN],low[MaxN],edge[MaxM],nextt[MaxM],first[MaxN];
bool visit[MaxN];
stack  s;
void addedge(int a,int b)
{
	edge[++tot]=b;
	nextt[tot]=first[a];
	first[a]=tot;
}
void dfs(int cow)
{
	timee++;
	dfn[cow]=low[cow]=timee;
	s.push(cow);
	visit[cow]=1;
	for (reg int i=first[cow];i!=-1;i=nextt[i])
	{
		if (!visit[edge[i]])
		{
			dfs(edge[i]);
			if (low[edge[i]]

 

                                                 D题

题面:

                                    D - Redundant Paths

In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1..F) to another field, Bessie and the rest of the herd are forced to cross near the Tree of Rotten Apples. The cows are now tired of often being forced to take a particular path and want to build some new paths so that they will always have a choice of at least two separate routes between any pair of fields. They currently have at least one route between each pair of fields and want to have at least two. Of course, they can only travel on Official Paths when they move from one field to another. 

Given a descri_ption of the current set of R (F-1 <= R <= 10,000) paths that each connect exactly two different fields, determine the minimum number of new paths (each of which connects exactly two fields) that must be built so that there are at least two separate routes between any pair of fields. Routes are considered separate if they use none of the same paths, even if they visit the same intermediate field along the way. 

There might already be more than one paths between the same pair of fields, and you may also build a new path that connects the same fields as some other path.

Input

Line 1: Two space-separated integers: F and R 

Lines 2..R+1: Each line contains two space-separated integers which are the fields at the endpoints of some path.

Output

Line 1: A single integer that is the number of new paths that must be built.

Sample Input

7 7
1 2
2 3
3 4
2 5
4 5
5 6
5 7

Sample Output

2

Hint

Explanation of the sample: 

One visualization of the paths is: 

1   2   3
   +---+---+  
       |   |
       |   |
 6 +---+---+ 4
      / 5
     / 
    / 
 7 +

Building new paths from 1 to 6 and from 4 to 7 satisfies the conditions. 

1   2   3
   +---+---+  
   :   |   |
   :   |   |
 6 +---+---+ 4
      / 5  :
     /     :
    /      :
 7 + - - - - 

Check some of the routes: 
1 – 2: 1 –> 2 and 1 –> 6 –> 5 –> 2 
1 – 4: 1 –> 2 –> 3 –> 4 and 1 –> 6 –> 5 –> 4 
3 – 7: 3 –> 4 –> 7 and 3 –> 2 –> 5 –> 7 
Every pair of fields is, in fact, connected by two routes. 

It's possible that adding some other path will also solve the problem (like one from 6 to 7). Adding two paths, however, is the minimum.

题面描述:

            这个题目讲的是,一些奶牛希望F个放牧场当中任意两个放牧场之间存在两条不同的路径,然后输入的R条路径当中保证F个放牧场之间的任意两个放牧场存在至少一条路径,问我们最少建设多少条路径来保证F个放牧场当中任意两个放牧场存在至少两条路径。

题目分析:

            我们知道在这些路径的强连通分量中的任意两个点必定存在两条路径,而我们需要将这些强连通分量进行缩点,排除在我们的考虑范围内,由于将所有的强连通分量进行缩点后,我们重新得到的图类似于一棵树的结构,然后我们只要将这个图的所有度为1的点连起来即可,由于题目保证了任意两个放牧场之间至少存在一条路径,所以不存在度为0的点。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int MaxF=5005;
const int MaxR=1e4+5;
int F,tot,timee,cnt;
int num[MaxF],dfn[MaxF],low[MaxF],first[MaxF],degree[MaxF];
int edge[MaxR*2],nextt[MaxR*2];
bool visit[MaxR*2];
stack  s;
void addedge(int a,int b)
{
	edge[tot]=b;
	nextt[tot]=first[a];
	first[a]=tot++;
}
void dfs(int field)
{
	dfn[field]=low[field]=++timee;
	s.push(field);
	for (reg int i=first[field];i!=-1;i=nextt[i])
	{
		if (!visit[i])
		{
			visit[i]=visit[i^1]=1;
			if (!dfn[edge[i]])
			{
				dfs(edge[i]);
				low[field]=min(low[field],low[edge[i]]);
				continue;
			}
			low[field]=min(low[field],dfn[edge[i]]);
		}
	}
	if (low[field]==dfn[field])
	{
		int temp;
		cnt++;
		do
		{
			temp=s.top();
			num[s.top()]=cnt;
			s.pop();
		} while (temp!=field);
	}
}
void Tarjan()
{
	memset(dfn,0,sizeof(dfn));
	memset(low,0,sizeof(low));
	memset(visit,0,sizeof(visit));
	for (reg int i=1;i<=F;i++)
	if (!dfn[i]) dfs(i);
}
int main()
{
	int R;
	while (~scanf("%d%d",&F,&R))
	{
		memset(first,-1,sizeof(first));
		memset(degree,0,sizeof(degree));
		cnt=tot=timee=0;
		for (reg int i=1;i<=R;i++)
		{
			int a,b;
			scanf("%d%d",&a,&b);
			addedge(a,b);
			addedge(b,a);
		}
		Tarjan();
		memset(visit,0,sizeof(visit));
		for (reg int i=1;i<=F;i++)
		{
			for (reg int j=first[i];j!=-1;j=nextt[j])
			if (num[edge[j]]!=num[i] && !visit[j])
			{
				visit[j]=visit[j^1]=1;
				degree[num[i]]++;
				degree[num[edge[j]]]++;
			}
		}
		int ans=0;
		for (reg int i=1;i<=cnt;i++)
		if (degree[i]==1) ans++;
		printf("%d\n",(ans+1)/2); 
	}
	return 0;
}

 

                                                 E题

题面:

                              E - Til the Cows Come Home

Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before Farmer John wakes her for the morning milking. Bessie needs her beauty sleep, so she wants to get back as quickly as possible. 

Farmer John's field has N (2 <= N <= 1000) landmarks in it, uniquely numbered 1..N. Landmark 1 is the barn; the apple tree grove in which Bessie stands all day is landmark N. Cows travel in the field using T (1 <= T <= 2000) bidirectional cow-trails of various lengths between the landmarks. Bessie is not confident of her navigation ability, so she always stays on a trail from its start to its end once she starts it. 

Given the trails between the landmarks, determine the minimum distance Bessie must walk to get back to the barn. It is guaranteed that some such route exists.

Input

* Line 1: Two integers: T and N 

* Lines 2..T+1: Each line describes a trail as three space-separated integers. The first two integers are the landmarks between which the trail travels. The third integer is the length of the trail, range 1..100.

Output

* Line 1: A single integer, the minimum distance that Bessie must travel to get from landmark N to landmark 1.

Sample Input

5 5
1 2 20
2 3 30
3 4 20
4 5 20
1 5 100

Sample Output

90

Hint

INPUT DETAILS: 

There are five landmarks. 

OUTPUT DETAILS: 

Bessie can get home by following trails 4, 3, 2, and 1.

题面描述:

            这个题目输入n个地标,T条双向的路径,然后让你求出从第一个地标到达第n个地标的最短路径。

题目分析:

            这个题目就是经典的单源最短路径问题,直接用Dijkstra算法求出第一个地表求出第n个地表的最短路径。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int MaxN=1005;
const int MaxT=2005;
struct node
{
	int t,len;
};
int tot;
int nextt[MaxT*2],first[MaxN],dist[MaxN];
node edge[MaxT*2];
bool operator < (node a,node b)
{
	return a.len q;
	memset(dist,INF,sizeof(dist));
	node temp;
	temp.t=1;temp.len=0;
	q.push(temp);
	dist[1]=0;
	while (!q.empty())
	{
		node temp=q.top();
		q.pop();
		int t=temp.t,len=temp.len;
		for (reg int i=first[t];i!=-1;i=nextt[i])
		if (len+edge[i].len

 

                                                 F题

题面:

                                       F - Roadblocks

Bessie has moved to a small farm and sometimes enjoys returning to visit one of her best friends. She does not want to get to her old home too quickly, because she likes the scenery along the way. She has decided to take the second-shortest rather than the shortest path. She knows there must be some second-shortest path.

The countryside consists of R (1 ≤ R ≤ 100,000) bidirectional roads, each linking two of the N (1 ≤ N ≤ 5000) intersections, conveniently numbered 1..N. Bessie starts at intersection 1, and her friend (the destination) is at intersection N.

The second-shortest path may share roads with any of the shortest paths, and it may backtrack i.e., use the same road or intersection more than once. The second-shortest path is the shortest path whose length is longer than the shortest path(s) (i.e., if two or more shortest paths exist, the second-shortest path is the one whose length is longer than those but no longer than any other path).

Input

Line 1: Two space-separated integers: N and R 
Lines 2.. R+1: Each line contains three space-separated integers: AB, and D that describe a road that connects intersections A and B and has length D (1 ≤ D ≤ 5000)

Output

Line 1: The length of the second shortest path between node 1 and node N

Sample Input

4 4
1 2 100
2 4 200
2 3 250
3 4 100

Sample Output

450

Hint

Two routes: 1 -> 2 -> 4 (length 100+200=300) and 1 -> 2 -> 3 -> 4 (length 100+250+100=450)

题面描述:

            这个题目求的是从第一个路口到达第n个路口的次短路径(即仅比最短路长的路径)。

题目分析:

            这个题目可以用Dijkstra算法在记录从第一个路口到达当前路口的最短路径的时候记录次短路径即可,这是因为从第一个路口到达当前路口的次短路径只能从前面状态的最短路径加上次短路径或者从前面状态的次短路径加上最短路径,所以我们可以在更新最短路径的时候顺便更新次短路径,最后输出我们记录的从第一个路口到达第n个路口的次短路径即可。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int MaxN=5005;
const int MaxR=1e5+5;
struct node
{
	int t,dist;
};
int N,tot;
node edge[MaxR*2];
int first[MaxN],dist[2][MaxN];
int nextt[MaxR*2];
bool visit[2][MaxN];
bool operator < (node a,node b)
{
	return a.dist

 

                                                 G题

题面:

                                           G - 有点难的

Petya loves volleyball very much. One day he was running late for a volleyball match. Petya hasn't bought his own car yet, that's why he had to take a taxi. The city has n junctions, some of which are connected by two-way roads. The length of each road is defined by some positive integer number of meters; the roads can have different lengths.

Initially each junction has exactly one taxi standing there. The taxi driver from the i-th junction agrees to drive Petya (perhaps through several intermediate junctions) to some other junction if the travel distance is not more than ti meters. Also, the cost of the ride doesn't depend on the distance and is equal to cibourles. Taxis can't stop in the middle of a road. Each taxi can be used no more than once. Petya can catch taxi only in the junction, where it stands initially.

At the moment Petya is located on the junction x and the volleyball stadium is on the junction y. Determine the minimum amount of money Petya will need to drive to the stadium.

Input

The first line contains two integers n and m (1 ≤ n ≤ 1000, 0 ≤ m ≤ 1000). They are the number of junctions and roads in the city correspondingly. The junctions are numbered from 1 to n, inclusive. The next line contains two integers x and y (1 ≤ x, y ≤ n). They are the numbers of the initial and final junctions correspondingly. Next m lines contain the roads' description. Each road is described by a group of three integers uiviwi (1 ≤ ui, vi ≤ n, 1 ≤ wi ≤ 109) — they are the numbers of the junctions connected by the road and the length of the road, correspondingly. The next n lines contain n pairs of integers ti and ci (1 ≤ ti, ci ≤ 109), which describe the taxi driver that waits at the i-th junction — the maximum distance he can drive and the drive's cost. The road can't connect the junction with itself, but between a pair of junctions there can be more than one road. All consecutive numbers in each line are separated by exactly one space character.

Output

If taxis can't drive Petya to the destination point, print "-1" (without the quotes). Otherwise, print the drive's minimum cost.

Please do not use the %lld specificator to read or write 64-bit integers in С++. It is preferred to use cin, cout streams or the %I64d specificator.

Examples

Input

4 4
1 3
1 2 3
1 4 1
2 4 1
2 3 5
2 7
7 2
1 2
7 7

Output

9

Note

An optimal way — ride from the junction 1 to 2 (via junction 4), then from 2 to 3. It costs 7+2=9 bourles.

题面描述:

            这个题目讲述的是,有n个路口,然后有m条路径连接这n个路口其中的两个,Petya现在身处第x个路口,然后排球场在第y个路口,然后每个路口都有一辆出租车,每辆出租车有各自能行驶的最大距离以及花费,然后题目问我们从第x个路口去到第y个路口最少需要花费多少。如果从第x个路口到达不了第y个路口的话就输出-1。

题目分析:

            这个题目需要求两次最短路径,我们第一次先预处理每个路口的出租车在满足行驶距离不超过最大的行驶距离的条件,我们从当前路口不断拓展到新的路口,记录当前路口到达其他路口的最短路径。

            第二次我们从第x个路口求出到达其他路口的最少花费,利用第一次处理出来满足条件的当前路口到达其他路口的方案,最后输出从第x个路口到达第y个路口的最少花费即可,如果不存在的话,输出-1即可。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define bll __int128
#define INF 0x3f3f3f3f3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
typedef pair P;
const int Maxn=1005;
const int Maxm=1005;
struct Edge
{
	int t,next;
	ll len;
};
struct Taxi
{
	ll t,c;
};
int n,tot;
int first[Maxn];
ll cost[Maxn],dist[Maxn][Maxn];
Edge edge[Maxm*2];
Taxi taxi[Maxn];
void addedge(int u,int v,ll w)
{
	edge[++tot].t=v;
	edge[tot].next=first[u];
	edge[tot].len=w;
	first[u]=tot;
}
void Dijkstra(int s)
{
	priority_queue ,greater

> q; dist[s][s]=0; q.push(P(s,dist[s][s])); while (!q.empty()) { P p=q.top(); q.pop(); int v=p.first; if (p.second>dist[s][v]) continue; for (reg int i=first[v];i!=-1;i=edge[i].next) { if (dist[s][v]+edge[i].len,greater

> q; fill(cost,cost+Maxn,INF); cost[s]=0; q.push(P(s,cost[s])); while (!q.empty()) { P p=q.top();q.pop(); int v=p.first; if (p.second>cost[v]) continue; for (reg int i=1;i<=n;i++) { if (dist[v][i]<=taxi[v].t && cost[v]+taxi[v].c>n>>m>>x>>y; memset(first,-1,sizeof(first)); tot=0; for (reg int i=1;i<=m;i++) { int u,v; ll w; cin>>u>>v>>w; addedge(u,v,w); addedge(v,u,w); } for (reg int i=1;i<=n;i++) { for (reg int j=1;j<=n;j++) dist[i][j]=INF; } for (reg int i=1;i<=n;i++) { cin>>taxi[i].t>>taxi[i].c; Dijkstra(i); } solve(x); if (cost[y]==INF) cout<<"-1"<

 

                                                 H题

题面:

                                             H - 很难

Okabe likes to be able to walk through his city on a path lit by street lamps. That way, he doesn't get beaten up by schoolchildren.

Okabe's city is represented by a 2D grid of cells. Rows are numbered from 1 to nfrom top to bottom, and columns are numbered 1 to m from left to right. Exactly kcells in the city are lit by a street lamp. It's guaranteed that the top-left cell is lit.

Okabe starts his walk from the top-left cell, and wants to reach the bottom-right cell. Of course, Okabe will only walk on lit cells, and he can only move to adjacent cells in the up, down, left, and right directions. However, Okabe can also temporarily light all the cells in any single row or column at a time if he pays 1coin, allowing him to walk through some cells not lit initially.

Note that Okabe can only light a single row or column at a time, and has to pay a coin every time he lights a new row or column. To change the row or column that is temporarily lit, he must stand at a cell that is lit initially. Also, once he removes his temporary light from a row or column, all cells in that row/column not initially lit are now not lit.

Help Okabe find the minimum number of coins he needs to pay to complete his walk!

Input

The first line of input contains three space-separated integers nm, and k (2 ≤ n, m, k ≤ 104).

Each of the next k lines contains two space-separated integers ri and ci (1 ≤ ri ≤ n, 1 ≤ ci ≤ m) — the row and the column of the i-th lit cell.

It is guaranteed that all k lit cells are distinct. It is guaranteed that the top-left cell is lit.

Output

Print the minimum number of coins Okabe needs to pay to complete his walk, or -1 if it's not possible.

Examples

Input

4 4 5
1 1
2 1
2 3
3 3
4 3

Output

2

Input

5 5 4
1 1
2 1
3 1
3 2

Output

-1

Input

2 2 4
1 1
1 2
2 1
2 2

Output

0

Input

5 5 4
1 1
2 2
3 3
4 4

Output

3

Note

In the first sample test, Okabe can take the path , paying only when moving to (2, 3) and (4, 4).

In the fourth sample, Okabe can take the path  , paying when moving to (1, 2), (3, 4), and (5, 4).

题面描述:

            题目输入一个由n*m个网格组成的一座城市,然后有k个被灯光照亮的网格,Okabe从(1,1)出发,每次可以向上,向下,向左或者向右走,但是必须保证每次到达的网格都是有灯光照亮的,Okabe可以使用一次魔法使任意一行或者任意一列都照亮,但是他如果要再次使用魔法的话,就要把先前使用的魔法撤销掉,每次使用魔法的话都要花费一个金币,然后题目问我们最少需要多少金币可以从(1,1)走到(n,m),如果走不到的话,就输出-1。

题目分析:

            这个题目由于原本照亮的点的个数比较多,如果我们每个点去判断和其他点的关系的话,那么这样的做法显然是时间复杂度比较高的,会出现超时的。

            首先我们知道如果两个被照亮的点相邻的话,那么我们不用花费任何金币就可以当中的一个点走到另外一个点。

            如果两个原本照亮的点在同一行或者同一列的话(不包含相邻的情况),那么我们知道只需要把相同的行照亮或者相同的列照亮就行,花费一个金币。

            如果两个原本照亮的点在相邻的行或者在相邻的列的话(不包含以上情况),那么我们从其中一个点走到另一个点只需要把另一个点所在的行或者所在的列照亮即可,花费一个金币。

            如果两个原本照亮的点隔着一行或者隔着一列的话(不包含以上情况),那么我们从其中一个点走到另一个点只需中间隔着的一行或者中间隔着的一列照亮即可,花费一个金币。

            我们可以看到除了相邻的情况之外,其他情况均与第几行和第几列有关,与这个点具体在第几行第几列关系并不是很大。

            因此我们可以在每一行和每一列引入两个虚点,一个是入点,每个入点连接着记录的这一行的所有点或者是记录的这一列的所有点,权值为0,一个是出点,每个出点被记录的这一行的所有点或者是记录的这一列的所有点所连接着,权值一样是0。那么每一行的具体关系就可以由这些虚点去表示,相邻的情况要必须先预处理,然后再处理好这些虚点的关系。

            在运用Dijkstra算法计算最少花费之前,要先把从(1,1)拓展得出来的所有原本照亮的点压入队列,Dijkstra算法结束后也一样,把能够拓展到(n,m)的花费都算出来,取最小值输出即可。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define bll __int128
#define INF 0x3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int Maxn=1e4+5;
const int Maxm=1e4+5;
const int Maxk=1e4+5;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1}; 
typedef pair p;
struct Cell
{
	int x,y;
};
struct Edge
{
	int t,val,next;
};
Edge edge[15000005];
Cell cell[Maxk];
map  s[Maxn];
int tot,kk,k;
int first[Maxk+(Maxn<<1)+(Maxm<<1)];
int dist[Maxk+(Maxn<<1)+(Maxm<<1)];
void addedge(int a,int b,int val)
{
	edge[++tot].t=b;
	edge[tot].val=val;
	edge[tot].next=first[a];
	first[a]=tot;
}
void Dijkstra()
{
	memset(dist,INF,sizeof(dist));
	priority_queue ,greater

> q; int t=-1; for (reg int i=1;i<=kk;i++) { if (cell[i].x==1 && cell[i].y==1) { t=i; dist[i]=0; q.push(p(0,i)); break; } } if (t==-1) { for (reg int i=1;i<=kk;i++) { if (abs(cell[i].x-1)<=1 || abs(cell[i].y-1)<=1) { dist[i]=1; q.push(p(1,i)); } } } while (!q.empty()) { p temp=q.top(); q.pop(); if (dist[temp.second]0) { addedge(s[xx][yy],i,0); addedge(i,s[xx][yy],0); } } } kk=k; k+=2*n+2*m; for (reg int i=1;i<=kk;i++) { addedge(i,cell[i].x+kk,0); addedge(cell[i].x+kk+n,i,0); addedge(i,cell[i].y+2*n+kk,0); addedge(cell[i].y+2*n+m+kk,i,0); } for (reg int i=1;i<=n;i++) { for (reg int j=-2;j<=2;j++) { int temp=i+j; if (temp<1 || temp>n) continue; addedge(i+kk,temp+kk+n,1); addedge(temp+kk,i+kk+n,1); } } for (reg int i=1;i<=m;i++) { for (reg int j=-2;j<=2;j++) { int temp=i+j; if (temp<1 || temp>m) continue; addedge(i+kk+2*n,temp+kk+2*n+m,1); addedge(temp+kk+2*n,i+kk+2*n+m,1); } } Dijkstra(); int ans=INF; for (reg int i=1;i<=kk;i++) { if (cell[i].x==n && cell[i].y==m) { ans=min(ans,dist[i]); continue; } if (abs(cell[i].x-n)<=1 || abs(cell[i].y-m)<=1) ans=min(ans,dist[i]+1); } printf("%d\n",ans==INF?-1:ans); } return 0; }

 

                                                 I题

题面:

                                         I - 畅通工程

某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路? 

Input

测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。 
注意:两个城市之间可以有多条道路相通,也就是说 
3 3 
1 2 
1 2 
2 1 
这种输入也是合法的 
当N为0时,输入结束,该用例不被处理。 

Output

对每个测试用例,在1行里输出最少还需要建设的道路数目。 

Sample Input

4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0

Sample Output

1
0
2
998
 

Hint

Huge input, scanf is recommended. 

题面描述:

            这个题目讲述的是,输入m条路径,问我们最少还需要修多少条路径去满足n个城镇相互之间至少存在一条路径。

题目分析:

            这个题目只要用并查集把相连的城镇构成一个集合,然后再去计算有多少个集合,根据贪心策略,我们最少可以用集合数减一的路径去把这些集合连接起来即可满足题目条件。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3fffffff
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int Maxn=1005;
int father[Maxn];
int find(int x)
{
	return x==father[x]?x:father[x]=find(father[x]);
}
void merge(int a,int b)
{
	int ta=find(a);
	int tb=find(b);
	if (ta!=tb) father[ta]=tb;
}
bool ok(int a,int b)
{
	return find(a)==find(b);
}
int main()
{
	int n,m;
	while (scanf("%d%d",&n,&m),n!=0)
	{
		int ans=n-1;
		for (reg int i=1;i<=n;i++) father[i]=i;
		for (reg int i=1;i<=m;i++)
		{
			int l,r;
			scanf("%d%d",&l,&r);
			if (ok(l,r)) continue;
			merge(l,r);ans--;
		}
		printf("%d\n",ans);
	}
	return 0;
}

 

                                                 J题

题面:

                                      J - Legal or Not

ACM-DIY is a large QQ group where many excellent acmers get together. It is so harmonious that just like a big family. Every day,many "holy cows" like HH, hh, AC, ZT, lcc, BF, Qinz and so on chat on-line to exchange their ideas. When someone has questions, many warm-hearted cows like Lost will come to help. Then the one being helped will call Lost "master", and Lost will have a nice "prentice". By and by, there are many pairs of "master and prentice". But then problem occurs: there are too many masters and too many prentices, how can we know whether it is legal or not?

We all know a master can have many prentices and a prentice may have a lot of masters too, it's legal. Nevertheless,some cows are not so honest, they hold illegal relationship. Take HH and 3xian for instant, HH is 3xian's master and, at the same time, 3xian is HH's master,which is quite illegal! To avoid this,please help us to judge whether their relationship is legal or not. 

Please note that the "master and prentice" relation is transitive. It means that if A is B's master ans B is C's master, then A is C's master.

Input

The input consists of several test cases. For each case, the first line contains two integers, N (members to be tested) and M (relationships to be tested)(2 <= N, M <= 100). Then M lines follow, each contains a pair of (x, y) which means x is y's master and y is x's prentice. The input is terminated by N = 0. 
TO MAKE IT SIMPLE, we give every one a number (0, 1, 2,..., N-1). We use their numbers instead of their names.

Output

For each test case, print in one line the judgement of the messy relationship. 
If it is legal, output "YES", otherwise "NO".

Sample Input

3 2
0 1
1 2
2 2
0 1
1 0
0 0

Sample Output

YES
NO

题面描述:

            题目输入奶牛的总数n,以及n头奶牛当中存在的m种关系,接下来的m行输入代表第一头奶牛教导第二头奶牛,然后问我们这m行输入是否合法。

题目分析:

            这个题目我们画图可以知道,我们将这m行输入的第一头奶牛连接第二头奶牛的话,那么我们发现只有这个图存在环的情况下才不合法,因此我们可以用拓扑排序来判断这个图是否存在环,有环就证明不合法,否则即为合法。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3fffffff
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int Maxn=105;
const int Maxm=105;
int n,m,tot,ans;
int edge[Maxm],nextt[Maxm],first[Maxn],cnt[Maxn];
void addedge(int a,int b)
{
	edge[++tot]=b;
	nextt[tot]=first[a];
	first[a]=tot;
	cnt[b]++;
}
void topsort()
{
	stack  q;
	for (reg int i=0;i

 

                                                 K题

题面:

                                       K - Exploration

Miceren likes exploration and he found a huge labyrinth underground! 

This labyrinth has N caves and some tunnels connecting some pairs of caves. 

There are two types of tunnel, one type of them can be passed in only one direction and the other can be passed in two directions. Tunnels will collapse immediately after Miceren passing them. 

Now, Miceren wants to choose a cave as his start point and visit at least one other cave, finally get back to start point. 

As his friend, you must help him to determine whether a start point satisfing his request exists.

Input

The first line contains a single integer T, indicating the number of test cases. 

Each test case begins with three integers N, M1, M2, indicating the number of caves, the number of undirectional tunnels, the number of directional tunnels. 

The next M1 lines contain the details of the undirectional tunnels. Each line contains two integers u, v meaning that there is a undirectional tunnel between u, v. (u ≠ v) 

The next M2 lines contain the details of the directional tunnels. Each line contains integers u, v meaning that there is a directional tunnel from u to v. (u ≠ v) 

T is about 100. 

1 ≤ N,M1,M2 ≤ 1000000. 

There may be some tunnels connect the same pair of caves. 

The ratio of test cases with N > 1000 is less than 5%.

Output

For each test queries, print the answer. If Miceren can do that, output "YES", otherwise "NO".

Sample Input

2
5 2 1
1 2
1 2
4 5
4 2 2
1 2
2 3
4 3
4 1

Sample Output

YES
NO

 

Hint

If you need a larger stack size,
please use #pragma comment(linker, "/STACK:102400000,102400000") and submit your solution using C++.

题面描述:

            这个题目讲述的是,有n个洞穴,然后又m1条双向隧道连接着n个洞穴当中的任意两个洞穴,m2条单向隧道连接着n个洞穴当中的任意两个洞穴,而且每条隧道仅可走一次。问我们是否可以把某一个洞穴设为起点,然后至少经过其他洞穴一次,最后回到起点。

题目分析:

             这个题目我们画图可以知道,如果存在环的话,那么就可以满足条件,但是由于这个题目存在双向路径,并且这些双向路径只能走一次,所以我们不能直接用拓扑排序去判断是否存在环。

             对于这些双向路径,我们需要用并查集去处理一下,我们对每条双向路径连接着的两个洞穴进行并查集的合并操作,经过这样的操作后,我们会发现每个集合当中的任意两个洞穴是可以相互到达的,因此我们可以对这些集合进行缩点操作,然后所有单向路径连接着的两个点我们用它们在各自的集合进行缩点后的点去表示,经过这样的操作过后,双向路径被我们处理掉了,剩下的只是单向路径,因此我们可以用拓扑排序去判断是否存在环即可。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
#define mod 1000000007
using namespace std;
const int MaxN=1e6+5;
const int MaxM1=1e6+5;
const int MaxM2=1e6+5;
int N,tot,ans;
int father[MaxN],first[MaxN],cnt[MaxN],edge[MaxM1+MaxM2],nextt[MaxM1+MaxM2];
int find(int t)
{
	if (t==father[t]) return t;
	father[t]=find(father[t]);
	return father[t];
}
void merge(int a,int b)
{
	int ta=find(a);
	int tb=find(b);
	if (ta!=tb) father[ta]=tb;
}
bool check(int a,int b)
{
	return find(a)==find(b);
}
void addedge(int a,int b)
{
	edge[++tot]=b;
	nextt[tot]=first[a];
	first[a]=tot;
	cnt[b]++;
}
void topsort()
{
	stack  q;
	for (reg int i=1;i<=N;i++)
	if (cnt[father[i]]==0) q.push(father[i]);
	while (!q.empty())
	{
		ans--;
		int num=q.top();q.pop();
		for (reg int i=first[num];i!=-1;i=nextt[i])
		if (--cnt[edge[i]]==0) q.push(edge[i]);
	}
}
int main()
{
	int T;
	scanf("%d",&T);
	while (T--)
	{
		int M1,M2;
		bool ff=0;
		scanf("%d%d%d",&N,&M1,&M2);
		for (reg int i=1;i<=N;i++) father[i]=i;
		for (reg int i=1;i<=M1;i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			if (ff) continue;
			if (check(u,v))
			{
				ff=1;continue;
			}
			merge(u,v);
		}
		ans=tot=0;
		if (!ff)
		{
			memset(first,-1,sizeof(first));
			memset(cnt,0,sizeof(cnt));
			for (reg int i=1;i<=N;i++)
			{
				father[i]=find(i);
				if (father[i]==i) ans++;
			}
		}
		for (reg int i=1;i<=M2;i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			if (ff) continue;
			addedge(father[u],father[v]);
		}
		if (ff)
		{
			printf("YES\n");
			continue;
		}
		topsort();
		if (ans>0) printf("YES\n");else printf("NO\n");
	}
	return 0;
}

 

                                                 L题

题面:

                                            L - 最短路

有一天雪菜和东马一起组队写代码,在连续WA了233次后,东马忍不住站起来大发雷霆,对雪菜说,

 

明明是我先写的,A题也好,调试也好,可是为什么会这样呢,你为什么WA的这么熟练啊!连这种简单题怎么都不会做?

 

我跟你讲,我可是身经百战了,哪个类型的题我没见过?你知道集训队的CerberuX菊苣吧,就是那个河老师,比你不知道高到哪里去啦,我和他谈笑风生啊!

 

监考老师正巧就是CerberuX老师,他听到了东马的声音注意到了他们,准备走过去提醒他们比赛时不要站起来大声讲话。可是为了避免走动时影响其他同学,他准备找一条最短的路径过去。

 

由于机房非常非常大,而且机器的布局也不规律,所以不同机位之间不一定有通路可以直接走过去,CerberuX一时半会找不出这样的一条路线,你能帮助他找到这条路并计算出需要多长时间才能走过去吗?

Input

输入包括多组数据。

 

每组数据第一行是两个整数N、M(N<=100,M<= 10000),

 

N表示集训队机房内电脑数量,标号为1的是CerberuX的位置,标号为N的是东马和雪菜的位置,M则表示机房内有多少条路。

 

N = M = 0表示输入结束。

 

接下来M行,每行包括3个整数A,B,C(1 <= A,B <= N,1 <= C <= 1000),表示在机位A与机位B之间有一条路,CerberuX需要C分钟的时间走过这条路。

Output

对于每组输入,输出一行,表示CerberuX从1号位置走到东马和雪菜位置的最短时间。如果CerberuX不能从1号位置走到东马和雪菜的位置,输出-10086。

Sample Input

2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0

Sample Output

3
2

Hint

CerberuX!

 

题面描述:

            这个题目讲述的是,输入n个电脑位置,然后又m条路径,每条路径有对应的时间,问我们从第一个电脑的位置走到第n个电脑的位置的最短时间。

题目分析:

            这个题目就直接用Dijkstra算法来求从第一个电脑位置到达第n个电脑位置的最短时间即可。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int Maxn=105;
const int Maxm=10005;
struct node
{
	int num,dist;
	
};
priority_queue  q;
int dist[Maxn],sign[Maxn],mapp[Maxn][Maxn];
bool operator < (node a,node b)
{
	if (a.dist!=b.dist) return a.dist>b.dist;
	return a.num>b.num;
}
int main()
{
	int n,m;
	while (scanf("%d%d",&n,&m),n!=0 || m!=0)
	{
		memset(mapp,INF,sizeof(mapp));
		memset(sign,0,sizeof(sign));
		memset(dist,INF,sizeof(dist));
		for (reg int i=1;i<=m;i++)
		{
			int A,B,C;
			node temp;
			scanf("%d%d%d",&A,&B,&C);
			mapp[A][B]=mapp[B][A]=C;
		}
		while (!q.empty()) q.pop();
		dist[1]=0;sign[1]=1;
		node temp;
		temp.num=1;temp.dist=0;
		q.push(temp);
		while (!q.empty())
		{
			for (reg int i=2;i<=n;i++)
			if (!sign[i] && q.top().dist+mapp[q.top().num][i]

 

                                                 M题

题面:

                                        M - 畅通工程续

某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。 

现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。

Input

本题目包含多组数据,请处理到文件结束。 
每组数据第一行包含两个正整数N和M(0 接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B 再接下一行有两个整数S,T(0<=S,T

Output

对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1. 

Sample Input

3 3
0 1 1
0 2 3
1 2 1
0 2
3 1
0 1 1
1 2

Sample Output

2
-1

题面描述:

            这个题目讲述的是,输入n个城镇,然后有m条道路,问我们从第s个城镇到第t个城镇的最短路径。

题目分析:

            这个题目就是直接用Dijkstra算法求从第s个城镇到其他城镇的最短路径即可,如果求出到达第t个城镇的最短路径的话,那么就输出-1。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int Maxn=205;
const int Maxm=1005;
struct node
{
	int num,dist;
};
struct Edge
{
	int next,val;
};
Edge edge[Maxm];
int tot,dist[Maxn],nextt[Maxm],first[Maxn];
bool operator < (node a,node b)
{
	return a.dist>b.dist;
}
void addedge(int a,int b,int val)
{
	edge[++tot].next=b;
	edge[tot].val=val;
	nextt[tot]=first[a];
	first[a]=tot;
}
int main()
{
	int n,m;
	while (~scanf("%d%d",&n,&m))
	{
		tot=0;
		memset(dist,INF,sizeof(dist));
		memset(first,-1,sizeof(first));
		for (reg int i=1;i<=m;i++)
		{
			int A,B,X;
			scanf("%d%d%d",&A,&B,&X);
			addedge(A,B,X);
			addedge(B,A,X);
		}
		int S,T;
		scanf("%d%d",&S,&T);
		priority_queue  q;
		dist[S]=0;
		node tt;
		tt.num=S;tt.dist=0;
		q.push(tt);
		while (!q.empty())
		{
			node temp=q.top();
			for (reg int i=first[temp.num];i!=-1;i=nextt[i])
			if (temp.dist+edge[i].val

 

                                                 N题

题面:

                                   N - Fedya and Maths

Fedya studies in a gymnasium. Fedya's maths hometask is to calculate the following expression:

(1n + 2n + 3n + 4nmod 5

for given value of n. Fedya managed to complete the task. Can you? Note that given number n can be extremely large (e.g. it can exceed any integer type of your programming language).

Input

The single line contains a single integer n (0 ≤ n ≤ 10105). The number doesn't contain any leading zeroes.

Output

Print the value of the expression without leading zeros.

Examples

Input

4

Output

4

Input

124356983594583453458888889

Output

0

Note

Operation x mod y means taking remainder after division x by y.

Note to the first sample:

题面描述:

            这个题目输入一个最大为10的10万次方的数n,问我们1的n次方,2的n次方,3的n次方和4的n次方加起来的结果对5取模的结果是多少。

题目分析:

            这个题目有多种做法去做,下面简单分析一下:

方法一:

             由于这个题目输入的n已经超过了所有的整数类型,所以我们只能用字符串去输入这个数n,由于这个n最多也就10万位,所以我们可以用一个循环去枚举n的每一位来求出答案。

             假设我们已经求出了2的n前i-1位对5取模的值,我们记为a^{b},假设n的第i位数字为c,那么2的n前i位对5取模的值可以表示为a^{10*b+c}=(a^{b})^{10}*a^{c}a^{b}对5取模后,显然是一个比5小的数,因此我们可以预处理出2的10次方,3的10次方以及4的10次方对5取模后的值,经过这样的预处理后,我们便可快速知道a^{10*b}对5取模后的值,然后c是一个0到9范围内的整数,因此我们也可以快速预处理出a^{c}对5取模后的值,两者再乘起来对5取模,便是2的n前i位对5取模后的值。

             3的n次方对5取模的值和4的n次方对5取模的值的求法与2的类似,从n的第一位枚举到最后一位后,再把1,2的n次方对5取模后的值,3的n次方对5取模后的值以及4的n次方对5取模后的值加起来再对5取模便可得出答案。

方法二(找规律):

             众所周知,1的n次方为1。

             2的0次方对5取模后为1,2的1次方对5取模后为2,2的2次方对5取模后为4,2的3次方对5取模后为3,2的4次方对5取模为1,......

             我们会发现2的各个次方对5取模后是一个有周期性的数列:1 2 4 3 1 2 4 3......

             3的0次方对5取模后为1,3的1次方对5取模后为3,3的2次方对5取模后为4,3的3次方对5取模后为2,3的4次方对5取模后为1,......

             我们会发现3的各个次方对5取模后是一个有周期性的数列:1 3 4 2 1 3 4 2......

             4的0次方对5取模后为1,4的1次方对5取模后为4,4的2次方对5取模后为1,4的3次方对5取模后为4,......

             我们会发现4的各个次方对5取模后是一个有周期性的数列:1 4 1 4 1 4 1 4......

             所以我们将这几个数列加起来的数列也是一个周期数列:4 0 0 0 4 0 0 0......

             因此n如果可以被4整除的话,那么答案为4,其余情况均为0。

方法三(欧拉定理):

             由于5是素数,所以1,2,3和4均与5互质,根据欧拉定理,得:a^{\varphi (m)}\equiv 1\: (mod\: m),欧拉函数\varphi (5)=4,所以当a=1,2,3和4时,我们可以得到4个式子。

             本题关键求的是a^{n}\: mod\: m,因此这里用到欧拉定理的一个扩展,a^{c}\equiv a^{c\: mod\: \varphi (m)}\: mod\: m,先将后面n\: mod\: \varphi (5)求出来,得到的是一个比4小的数,因此我们可以用一个循环或者用快速幂来求出答案。

欧拉定理的证明如下:

https://blog.csdn.net/hzj1054689699/article/details/80693756

代码:

方法一:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int Maxn=1e5+5;
char n[Maxn];
int mi[5][15];
int main()
{
	cin>>n;
	mi[1][0]=mi[2][0]=mi[3][0]=mi[4][0]=1;
	for (reg int i=1;i<=10;i++)
	{
		mi[1][i]=(mi[1][i-1]*1)%5;
		mi[2][i]=(mi[2][i-1]*2)%5;
		mi[3][i]=(mi[3][i-1]*3)%5;
		mi[4][i]=(mi[4][i-1]*4)%5;
	}
	int m2=1,m3=1,m4=1;
	for (reg int i=0;i

方法二:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int Maxn=1e5+5;
char n[Maxn];
int main()
{
	cin>>n;
	int t=0;
	for (reg int i=0;i

方法三(欧拉定理):

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int Maxn=1e5+5;
char n[Maxn];
int ksm(int p,int n)
{
	int ans=1;
	while (n)
	{
		if (n&1) ans=(ans*p)%5;
		p=(p*p)%5;
		n>>=1;
	}
	return ans;
}
int main()
{
	cin>>n;
	int t=0;
	for (reg int i=0;i

 

                                                 O题

题面:

                                        O - k-rounding

For a given positive integer n denote its k-rounding as the minimum positive integer x, such that x ends with k or more zeros in base 10 and is divisible by n.

For example, 4-rounding of 375 is 375·80 = 30000. 30000 is the minimum integer such that it ends with 4 or more zeros and is divisible by 375.

Write a program that will perform the k-rounding of n.

Input

The only line contains two integers n and k (1 ≤ n ≤ 109, 0 ≤ k ≤ 8).

Output

Print the k-rounding of n.

Examples

Input

375 4

Output

30000

Input

10000 1

Output

10000

Input

38101 0

Output

38101

Input

123456789 8

Output

12345678900000000

题面描述:

            这个题目讲述的是,输入两个数n和k,然后让我们求出n的某个倍数最少要有k个后缀0,并且这个数尽可能的小,让我们输出这个数。

题目分析:

            首先我们先把10的k次方算出来,因为题目要求的这个数的因子包含10的k次方以及n,所以只有找到一个数的因子含有这两个数即可,由于题目要求这个数尽可能小,所以我们将10的k次方和n的最小公倍数求出来便是答案。

            注意:由于本题的n最大为10的9次方,k最大为8,因此我们需要用long long类型的变量来记录答案。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
ll gcd(ll n,ll m)
{
	return n%m?gcd(m,n%m):m;
}
int main()
{
	ll n,num=1;
	int k;
	scanf("%lld%d",&n,&k);
	for (reg int i=1;i<=k;i++) num=num*10;
	ll temp=gcd(n,num);
	printf("%lld\n",n/temp*num);
	return 0;
}

 

                                                 P题

题面:

                                  P - Beautiful Numbers

Vitaly is a very weird man. He's got two favorite digits a and b. Vitaly calls a positive integer good, if the decimal representation of this integer only contains digits a and b. Vitaly calls a good number excellent, if the sum of its digits is a good number.

For example, let's say that Vitaly's favourite digits are 1 and 3, then number 12isn't good and numbers 13 or 311 are. Also, number 111 is excellent and number 11isn't.

Now Vitaly is wondering, how many excellent numbers of length exactly n are there. As this number can be rather large, he asks you to count the remainder after dividing it by 1000000007 (109 + 7).

A number's length is the number of digits in its decimal representation without leading zeroes.

Input

The first line contains three integers: abn (1 ≤ a < b ≤ 9, 1 ≤ n ≤ 106).

Output

Print a single integer — the answer to the problem modulo 1000000007 (109 + 7).

Examples

Input

1 3 3

Output

1

Input

2 3 10

Output

165

题面描述:

            这个题目输入三个整型变量,分别是a,b和n,如果一个数仅由a和b组成的话,那么这个数被称为好的数,那么如果这个数每个位上的数字加起来之和也是一个好的数的话,那么这个数就被称为一个卓越的数,现在题目问我们位数为n的正整数当中,其中卓越的数有多少个,不包含前导0。

题目分析:

            首先我们假设一个n位数包括k个a(0<=k<=n)和n-k个b,然后这个n位数各个位上的数字之和即为k*a+(n-k)*b,然后我们判断这个n位数各个位上的数字之和的这个数是否仅有a和b构成即可,如果是的话,那么总方案数加上C_{n}^{k},如果不是的话,我们枚举下一个可能的方案,直到枚举完所有的方案后结束程序。

            注意:由于本题由于总方案数可能过大,所以要进行取模运算,所以我们要用到费马小定理去求逆元来方便求解。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
#define mod 1000000007
using namespace std;
const int Maxn=1e6+5;
ll factorial[Maxn];
ll Flt(ll temp,ll p)
{
	ll ans=1;
	while (p)
	{
		if (p&1) ans=(ans*temp)%mod;
		temp=(temp*temp)%mod;
		p>>=1;
	}
	return ans;
}
int main()
{
	int a,b,n;
	scanf("%d%d%d",&a,&b,&n);
	int sum=b*n+b-a;
	factorial[0]=1;
	for (reg int i=1;i<=n;i++) factorial[i]=(factorial[i-1]*i)%mod;
	ll ans=0;
	for (reg int i=0;i<=n;i++)
	{
		sum=sum-b+a;
		int num=sum;
		while (num)
		{
			if (num%10!=a && num%10!=b) break;
			num/=10;
		}
		if (num!=0) continue;
		ans=(ans+(factorial[n]*Flt((factorial[i]*factorial[n-i])%mod,mod-2))%mod)%mod;
	}
	printf("%lld\n",ans);
	return 0;
}

 

                                                 Q题

题面:

                                       Q - Max Factor

To improve the organization of his farm, Farmer John labels each of his N (1 <= N <= 5,000) cows with a distinct serial number in the range 1..20,000. Unfortunately, he is unaware that the cows interpret some serial numbers as better than others. In particular, a cow whose serial number has the highest prime factor enjoys the highest social standing among all the other cows. 

(Recall that a prime number is just a number that has no divisors except for 1 and itself. The number 7 is prime while the number 6, being divisible by 2 and 3, is not). 

Given a set of N (1 <= N <= 5,000) serial numbers in the range 1..20,000, determine the one that has the largest prime factor. 

Input

* Line 1: A single integer, N 

* Lines 2..N+1: The serial numbers to be tested, one per line

Output

* Line 1: The integer with the largest prime factor. If there are more than one, output the one that appears earliest in the input file.

Sample Input

4
36
38
40
42

Sample Output

38

题面描述:

            这个题目讲述的是,输入n个数,然后让我们求出这n个数当中最早出现最大质因子的数是多少。

题目分析:

            这个题目由于n比较小,而且题目输入的n个数的范围大小又不是很大,因此我们可以将n个数当中的每个数进行质因数分解,然后用一个变量与n个数当中的每个数分解出来的质因子进行比较,如果分解出来的质因子比这个变量记录的之前的那些数的最大质因子还要大的话,那么我们需要更新这个变量记录的数值,并且用一个变量记录这个当前最早出现最大质因子的数,然后把这个变量记录的答案输出即可。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
int div(int num)
{
	int ans=0;
	for (reg int i=2;i*i<=num;i++)
	{
		if (num%i!=0) continue;
		while (num%i==0) num/=i;
		ans=max(ans,i);
	}
	if (num>=1) ans=max(ans,num);
	return ans;
}
int main()
{
	int n;
	while (~scanf("%d",&n))
	{
		int ans=1,sign=1;
		for (reg int i=1;i<=n;i++)
		{
			int num,temp;
			scanf("%d",&num);
			temp=div(num);
			if (temp>ans)
			{
				ans=temp;sign=num;
			}
		}
		printf("%d\n",sign);
	}
	return 0;
}

 

                                                 R题

题面:

                                    R - Revenge of GCD

In mathematics, the greatest common divisor (gcd), also known as the greatest common factor (gcf), highest common factor (hcf), or greatest common measure (gcm), of two or more integers (when at least one of them is not zero), is the largest positive integer that divides the numbers without a remainder. 
---Wikipedia 

Today, GCD takes revenge on you. You have to figure out the k-th GCD of X and Y.

Input

The first line contains a single integer T, indicating the number of test cases. 

Each test case only contains three integers X, Y and K. 

[Technical Specification] 
1. 1 <= T <= 100 
2. 1 <= X, Y, K <= 1 000 000 000 000 

Output

For each test case, output the k-th GCD of X and Y. If no such integer exists, output -1.

Sample Input

3
2 3 1
2 3 2
8 16 3

Sample Output

1
-1
2

题面描述:

            这个题目有多组数据,然后输入两个数x和y,问我们x和y的第k大公因数是多少,如果不存在的话,就输出-1。

题目分析:

            这个题目我们首先先算出x和y的最大公因数出来,然后分情况来判断。

            第一种情况:如果x和y的最大公因数是1的话,那么我们直接可以根据k的大小来判断输出结果,如果k为1的话,那么我们就可以直接输出1;如果k大于1的话,那么我们就可以直接输出-1。

            第二种情况:如果x和y的最大公因数大于1的话,那么我们就可以从2枚举到x和y的最大公因数的开平方,来求出x和y的最大公因数的所有因子,然后再将这些因子从小到大排序,然后最后倒数第k个因子即为答案(这是因为x和y的第k大公因数肯定是x和y的最大公因数的因子),所以x和y的最大公因数的第k大因子便为答案,如果k大于x和y的最大公因数的因子个数的话,那么就输出-1即可。

            由于x和y最大可以是1e12,因此我们要用long long来储存,开平方后是1e6,再乘上数据组数后的时间复杂度大概就是O(1e8),勉强不会超时。

            这里值得注意的是,求x和y的最大公因数的开平方需要加一个特别的判断,以避免将两个相同的开平方数重复加入。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
vector  v;
ll gcd(ll n,ll m)
{
	return n%m?gcd(m,n%m):m;
}
int main()
{
	int T;
	scanf("%d",&T);
	while (T--)
	{
		v.clear();
		ll X,Y,K,i;
		scanf("%lld%lld%lld",&X,&Y,&K);
		ll temp=gcd(min(X,Y),max(X,Y));
		v.push_back(1);
		if (temp==1)
		{
			if (K>1) printf("-1\n");else printf("1\n");
			continue;
		}
		v.push_back(temp);
		for (i=2;iv.size())
		{
			printf("-1\n");
			continue;
		}
		sort(v.begin(),v.end());
		printf("%lld\n",v[v.size()-K]);
	}
	return 0;
}

 

                                                 S题

题面:

                                           S - 美素数

  小明对数的研究比较热爱,一谈到数,脑子里就涌现出好多数的问题,今天,小明想考考你对素数的认识。 
  问题是这样的:一个十进制数,如果是素数,而且它的各位数字和也是素数,则称之为“美素数”,如29,本身是素数,而且2+9 = 11也是素数,所以它是美素数。 
  给定一个区间,你能计算出这个区间内有多少个美素数吗?

Input

第一行输入一个正整数T,表示总共有T组数据(T <= 10000)。 
接下来共T行,每行输入两个整数L,R(1<= L <= R <= 1000000),表示区间的左值和右值。

Output

对于每组数据,先输出Case数,然后输出区间内美素数的个数(包括端点值L,R)。 
每组数据占一行,具体输出格式参见样例。

Sample Input

3
1 100
2 2
3 19

Sample Output

Case #1: 14
Case #2: 1
Case #3: 4

题面描述:

            这个题目含有多组数据,每组数据输入两个变量l和r,分别代表区间的左端点与右端点,然后问我们在这个区间内有多少个美素数。所谓美素数就是满足这个数是一个素数以及这个素数的每一个数字位上的数字之和也是一个素数。

题目分析:

            这个题目输入的区间的长度最大可达1e6,然后数据组数最多有1e4组,如果直接做的话肯定会超时。

            因此我们可以先对1到1e6范围内的所有数用线性筛法把所有素数给全部筛出来,然后再把筛出来的素数的每一位分解出来相加判断是否为素数,如果是素数的话,那么就证明是美素数,那么我们可以用一个数组来这些美素数记录下来。

            经过上面的预处理后,我们只要对每组输入的数据进行如下处理即可得出答案,首先我们先求出1到r范围内美素数有多少个,由于我们在上面记录美素数的时候是有序的,因此我们可以用二分来找到一个恰好小于等于r的美素数,然后返回前面有多少个美素数即可;与上面做法一样,我们同样求出1到l-1范围内美素数的个数,最后两者相减即为答案。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
int len,cnt[100005],prime[100005];
bool sign[1000005];
int solve(int num)
{
	int low=0,high=len;
	while (low<=high)
	{
		int mid=(low+high)>>1;
		if (cnt[mid]<=num) low=mid+1;else high=mid-1;
	}
	return high;
}
int main()
{
	int tot=0;len=0;
	for (reg int i=2;i<=1000000;i++)
	{
		if (!sign[i]) prime[tot++]=i;
		for (reg int j=0;j

 

                                                 T题

题面:

                                              T - A/B

要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1)。

Input

数据的第一行是一个T,表示有T组数据。 
每组数据有两个数n(0 <= n < 9973)和B(1 <= B <= 10^9)。

Output

对应每组数据输出(A/B)%9973。

Sample Input

2
1000 53
87 123456789

Sample Output

7922
6060

题面描述:

            这个题目含有多组数据,每组数据输入两个变量n和B,由于A很大,所以n=A%9973,问题要我们求的是(A/B)%9973。

题目分析:

            这个题目要求的是(A/B)%9973,由于A很大,我们可能无法求出A并且用一个整型变量取储存A,因此我们设法求出A是不可行的。

            但是经过相关转化后,我们就会发现问题会变得简单,(A/B)%9973=n*inv(B)%9973,这个式子是成立的,因此我们只需求出B的逆元然后再乘上n对9973取模后即为答案。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3fffffff
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
#define mod 9973
using namespace std;
ll Flt(ll temp,int p)
{
	ll ans=1;
	while (p)
	{
		if (p&1) ans=(ans*temp)%mod;
		temp=(temp*temp)%mod;
		p>>=1;
	}
	return ans;
}
int main()
{
	int T;
	scanf("%d",&T);
	while (T--)
	{
		int n;
		ll B;
		scanf("%d%lld",&n,&B);
		ll ans=(n*Flt(B,mod-2))%mod;
		printf("%lld\n",ans);
	}
	return 0;
}

 

                                                 U题

题面:

                                       U - 青蛙的约会

两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面。 
我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度1米,这样我们就得到了一条首尾相接的数轴。设青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,两只青蛙跳一次所花费的时间相同。纬度线总长L米。现在要你求出它们跳了几次以后才会碰面。 

Input

输入只包括一行5个整数x,y,m,n,L,其中x≠y < 2000000000,0 < m、n < 2000000000,0 < L < 2100000000。

Output

输出碰面所需要的跳跃次数,如果永远不可能碰面则输出一行"Impossible"

Sample Input

1 2 3 4 5

Sample Output

4

题面描述:

            这个题目讲述的是,两只青蛙在同一纬度线上往同一方向跳,题目输入第一只青蛙的坐标x,第一只青蛙一次可以跳m米,第二只青蛙的坐标y,第二只青娃一次可以条n米,然后两只青蛙所在的纬度线长度为L米,问我们两只青蛙最少需要跳几次后可以相遇。如果两只青蛙不能相遇的话,那么就输出"Impossible"(不包括引号)。

题目分析:

            根据题目的意思,我们可以列出以下式子:

            x+u*m-y-u*n= k*L

            k*L+u*(n-m)=x-y

           由于k和u都是未知数,因此我们可以利用扩展欧几里得算法来判断解是否存在,因此我们首先利用扩展欧几里得算法求出L和n-m的最大公因数,然后判断L和n-m的最大公因数是否能整除x-y,如果可以的话,那么证明答案存在,如果不行的话,就直接输出"Impossible"(不包括引号)。

           通过扩展欧几里得算法,我们可以求出k,但是值得注意的是,这里求到的k可能是负数,因此我们需要将它转化成最小正解。

           假设存在一组解(k_{1},u_{1})满足k*L+u*(n-m)=x-y

           假设存在另外一组解(k_{2},u_{2})满足k*L+u*(n-m)=x-y

           因此可以得出k_{1}*L+u_{1}*(n-m)=k_{2}*L+u_{2}*(n-m)

                                L*(k_{1}-k_{2})=(n-m)*(u_{2}-u_{1})

           假设g=gcd(L,n-m),上面式子两边除以g后得,L^{'}*(k_{1}-k_{2})=(n-m)^{'}*(u_{2}-u_{1})

           L^{'}=L/g,(n-m)^{'}=(n-m)/g

           可以发现L^{'}(n-m)^{'}是互质的,因此L^{'}是可以整除(u_{2}-u_{1}),同理,(n-m)^{'}可以整除(k_{1}-k_{2})

           所以k*L+u*(n-m)=x-y的任意一组解可以写成(k+p*(n-m)^{'},u-p*L^{'}),因此就可以通过这样的方法来求得最小满足题目要求的正解。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3fffffff
#define min(a,b) (ab?a:b)
#define lowbit(x) (x&(-x))
#define mod 9973
using namespace std;
ll exgcd(ll a,ll &x,ll b,ll &y)
{
	if (b==0)
	{
		x=1;y=0;
		return a;
	}
	ll temp=exgcd(b,y,a%b,x);
	y-=a/b*x;
	return temp;
}
int main()
{
	ll x,y,m,n,L,t,ans;
	while (~scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&L))
	{
		ll gcd=exgcd(n-m,ans,L,t);
		if ((x-y)%gcd!=0 || n==m)
		{
			printf("Impossible\n");
			continue;
		}
		ans=ans*(x-y)/gcd;
		ans=(ans%(L/gcd)+L/gcd)%(L/gcd);
		printf("%lld\n",ans);
	}
	return 0;
}

 

你可能感兴趣的:(2019,GDUT,Winter,Training)