BC#78 (div.2)CA Loves GCD【N个数gcd】

来源:互联网 发布:海信32寸网络电视 编辑:程序博客网 时间:2024/06/05 22:43

CA Loves GCD

 
 Accepts: 64
 
 Submissions: 535
 Time Limit: 6000/3000 MS (Java/Others)
 
 Memory Limit: 262144/262144 K (Java/Others)
问题描述
CA喜欢是一个热爱党和人民的优秀同♂志,所以他也非常喜欢GCD(请在输入法中输入GCD得到CA喜欢GCD的原因)。现在他有N个不同的数,每次他会从中选出若干个(至少一个数),求出所有数的GCD然后放回去。为了使自己不会无聊,CA会把每种不同的选法都选一遍,CA想知道他得到的所有GCD的和是多少。我们认为两种选法不同,当且仅当有一个数在其中一种选法中被选中了,而在另外一种选法中没有被选中。
输入描述
第一行 TT,表示有 TT 组数据。接下来 TT 组数据,每组数据第一行一个整数 NN,表示CA的数的个数,接下来一行 NN 个整数 A_iAi 表示CA的每个数。1 \le T \le 50,~1 \le N \le 1000,~1 \le A_i \le 10001T50, 1N1000, 1Ai1000
输出描述
对于每组数据输出一行一个整数表示CA所有的选法的GCD的和对 100000007100000007 取模的结果。
输入样例
222 431 2 3
输出样例
810

Statistic | Submit | Clarifications | Back

看了人家的代码,暴力过,不过暴力的思维复杂度有点赶,就是目前这个数 和 前面所有子集的gcd,具体看代码,有注释

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int MOD=100000007;long long gcd[1010];int a[1010];int gc(int x,int y)//现在才发现x,y不分大小{    if(x==0)        return y;    return gc(y%x,x);}int main(){    int t,n,i,j,x;    long long sum;    scanf("%d",&t);    while(t--)    {        memset(gcd,0,sizeof(gcd));        scanf("%d",&n);        for(i=1; i<=n; i++)            scanf("%d",&a[i]);        for(i=1; i<=n; i++)        {            for(j=1; j<=1000; j++)            {                if(gcd[j]!=0)                {                    x=gc(a[i],j);//求gcd                    gcd[x]=(gcd[x]+gcd[j])%MOD;//gcd[x]表示当前最大公因数为x的子集的个数                }            }            gcd[a[i]]++;        }        sum=0;        for(i=1; i<=1000; i++)            sum=(sum+gcd[i]*i%MOD)%MOD;//gcd为i的子集个数乘以i,加起来为总和        //gcd[]数组要用long long,因为gcd[i]*1000的最大值为 100000006*1000        printf("%I64d\n",sum);    }}



0 0
原创粉丝点击