ZOJ 3846 GCD Reduce//水啊水啊水啊水
You are given a sequence {A1, A2, ..., AN}. You task is to change all the element of the sequence to 1 with the following operations (you may need to apply it multiple times):
- choose two indexes i and j (1 ≤ i < j ≤ N);
- change both Ai and Aj to gcd(Ai, Aj), where gcd(Ai, Aj) is the greatest common divisor of Ai and Aj.
You do not need to minimize the number of used operations. However, you need to make sure that there are at most 5N operations.
Input
Input will consist of multiple test cases.
The first line of each case contains one integer N (1 ≤ N ≤ 105), indicating the length of the sequence. The second line contains N integers, A1, A2, ..., AN (1 ≤ Ai ≤ 109).
Output
For each test case, print a line containing the test case number (beginning with 1) followed by one integer M, indicating the number of operations needed. You must assure that M is no larger than 5N. If you cannot find a solution, make M equal to -1 and ignore the following output.
In the next M lines, each contains two integers i and j (1 ≤ i < j ≤ N), indicating an operation, separated by one space.
If there are multiple answers, you can print any of them.
Remember to print a blank line after each case. But extra spaces and blank lines are not allowed.
Sample Input
4 2 2 3 4 4 2 2 2 2
Sample Output
Case 1: 3 1 3 1 2 1 4 Case 2: -1
题意:给你N个数,每次任意选取两个数,然后这两个数的值会变成gcd(a,b),如果能把整个序列都变成1的话,求选择的顺序;
思路:很明显只要做出1就行了,gcd(1,x)=1,我从第一个数开始一直向后面去gcd,取到第i个数肯定就是那么1的值前i个数的gcd,只要判断一直取到最后一个第1个数有没有变成1就行了,判断有之后,说明除了第一个数其他的n-1个数肯定会是有一个数跟第一个数的gcd为1,反证法就能很好的证明,那么只要第一个数跟另外的n-1个数依次取gcd,碰到互质就跳出来,并记录点,那么只要先选择1和这个点,剩下的n-2个数直接和1取就行了,但是这样交上去时wa的。。。你第一个数依次和后面的数取gcd那么取到最后一个的时候,1这个数肯定是前n个数的最大公约数,如果第一个数此时为1的话,那么再进行一次操作就好了,要求操作次数小于5*n,这个时候只是2*(n-1),完全是可以的,这样交上去是对的,反过来想,第一个数取到最后为1,那么最后一个数肯定这个时候也为1啊,我从后面往前GCD肯定也是对的,但是这样写的话交上去也是wa的,应该是special judge没有写好。。。
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 using namespace std; 5 #define N 100100 6 int a[N]; 7 int gcd(int a,int b) 8 { 9 if(b==0) return a; 10 return gcd(b,a%b); 11 } 12 int main() 13 { 14 int n; 15 int cnt=0; 16 while(scanf("%d",&n)!=EOF) 17 { 18 cnt++; 19 for(int i=1;i<=n;i++) 20 scanf("%d",&a[i]); 21 int res=a[1]; 22 for(int i=2;i<=n;i++) 23 res=gcd(res,a[i]); 24 if(res!=1) 25 printf("Case %d: -1\n\n",cnt); 26 else 27 { 28 printf("Case %d: %d\n",cnt,2*(n-1)); 29 for(int i=2;i<=n;i++) 30 printf("1 %d\n",i); 31 for(int i=2;i<=n;i++) 32 printf("1 %d\n",i); 33 printf("\n"); 34 } 35 } 36 return 0; 37 }