zoukankan      html  css  js  c++  java
  • CCPC2018 桂林 G "Greatest Common Divisor"(数学)

    UPC备战省赛组队训练赛第十七场

                with zyd,mxl

    G: Greatest Common Divisor

    题目描述
        There is an array of length n, containing only positive numbers.
        Now you can add all numbers by 1 many times. 
        Please find out the minimum times you need to perform to obtain an array whose greatest common divisor(gcd) is larger than 1 or state that it is impossible.
        You should notice that if you want to add one number by 1, you need to add all numbers by 1 at the same time.
    
    
    输入
        The first line of input file contains an integer T (1≤T≤20), describing the number of test cases.
        Then there are 2×T lines, with every two lines representing a test case.
        The first line of each case contains a single integer n (1≤n≤1e5) described above.
        The second line of that contains n integers ranging in [1,1e9].
    
    
    输出
        You should output exactly T lines.
        For each test case, print Case d: (d represents the order of the test case) first. 
        Then output exactly one integer representing the answer. 
        If it is impossible, print -1 instead.
    题目描述
    样例输入
    3
    
    1
    2
    
    5
    2 5 9 5 7
    
    5
    3 5 7 9 11
    
    样例输出
    Case 1: 0
    Case 2: -1
    Case 3: 1
    样例输入输出

    题意:

      定义a[]数组存储输入的 n 个数;

      求使得 ∀i∈[1,n] GCD(a[i]+x) > 1 的最小的 x;

      如果不存在这样的x,输出-1;

    思路:

      将数组 a 排序,去重;

      ①去重后,如果只有一个元素,输出 (a[1] == 1 ? 1:0);

      ②找到相邻两数差值的GCD记为gcd:

        (2.1)如果 gcd == 1 ,输出 -1

        (2.2)反之,所有数肯定可以通过增加 x 使得所有数变为 gcd 的倍数,当然也可以变为gcd因子的倍数,

          求解出最小的x输出;

    AC代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 const int maxn=1e5+50;
     5 
     6 int n;
     7 int a[maxn];
     8 
     9 int GCD(int _a,int _b)
    10 {
    11     return _a == 0 ? _b:GCD(_b%_a,_a);
    12 }
    13 ll Solve()
    14 {
    15     sort(a+1,a+n+1);
    16     int t=unique(a+1,a+n+1)-a;
    17     t--;
    18     if(t == 1)///情况①
    19         return a[1] == 1 ? 1:0;
    20 
    21     ll gcd=a[2]-a[1];
    22     for(int i=2;i <= t;++i)
    23         gcd=GCD(gcd,a[i]-a[i-1]);
    24 
    25     if(gcd == 1)///情况(2.1)
    26         return -1;
    27     ll ans=(a[1]/gcd+(a[1]%gcd == 0 ? 0:1))*gcd-a[1];///情况(2.2)
    28     for(ll i=2;i*i <= gcd;++i)
    29     {
    30         if(gcd%i != 0)
    31             continue;
    32         ll j=gcd/i;
    33         ///找到最小的 curAns 使得所有数 +curAns 都可以变为 i,j 的倍数
    34         ll curAns=(a[1]/i+(a[1]%i == 0 ? 0:1))*i-a[1];
    35         curAns=min(curAns,(a[1]/j+(a[1]%j == 0 ? 0:1))*j-a[1]);
    36         ans=min(ans,curAns);
    37     }
    38     return ans;
    39 }
    40 int main()
    41 {
    42     int test;
    43     scanf("%d",&test);
    44     for(int kase=1;kase <= test;++kase)
    45     {
    46         scanf("%d",&n);
    47         for(int i=1;i <= n;++i)
    48             scanf("%d",a+i);
    49 
    50         printf("Case %d: %lld
    ",kase,Solve());
    51     }
    52     return 0;
    53 }
    View Code

    小结:

     1 比赛的时候,只考虑了使所有的数都变成gcd的最小的因子的倍数的情况;
     2 并没有考虑到所有数变成gcd的其他因子的倍数使得答案最小;
     3 赛后,吃完午饭美美的睡上了一觉;
     4 午睡刚醒,就看到队友zyd给我发的G题ac的截图;
     5 一脸懵逼的我问了句为啥????
     6 例如
     7     13 34
     8     差值为21
     9     21的非1的因子有3,7,21
    10     所有数都变成3的倍数需要 +2
    11     所有数都变成7的倍数需要 +1
    12     所有数都变成21的倍数需要 +8
    13     答案当然是1啦,所以说,最优解不一定是变成gcd最小因子的倍数
    View Code
  • 相关阅读:
    上传项目到github上
    app widget设置bitmap时,无作用
    Android Studio 启动app 白屏
    android sqlite 数据库中使用的类型
    android 解决华为系列手机调试时不能打印Logcat日志信息
    android 自定义滚动条图标
    检测邮箱
    js检测是否存在中文
    表单的checkbox选中和取消
    javascript
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/10802641.html
Copyright © 2011-2022 走看看