链接: http://acm.hdu.edu.cn/showproblem.php?pid=5656
问题描述
CA是一位热爱党和人民的好同志; 她也不可避免地喜欢GCD(最大的共同除数)。
现在,有ñ不同的数字。每次,CA将选择几个数字(至少一个),并找到这些数字的GCD。为了获得乐趣,CA将尝试每一个选择。在那之后,她想知道所有GCD的总和。
当且仅当选择中存在数字但在另一个数字中不存在时,我们认为这两个选择彼此不同。
输入
第一行包含 Ť 表示测试用例的数量。
Ť测试用语如下。每个测试用例在第一次包含一个整数,表示ñ,CA的数量。第二行是ñ数字。
我们保证测试中的所有数字都在[1,1000]范围内。
1 ≤ Ť≤ 50
产量
Ť 线条,每一行打印GCDs mod的总和 100000007。
样本输入
2
2
2 4
3
1 2 3
样本输出
8
10
思路
一开始拿到这道题的时候,想到的是爆搜,把所有的n的排列全部都找出来,求他们的GCD,之后累加。但是看了一眼数据范围,显然不行。
之后就开始请教题解,学到了一个新的解决方法。转载于:https://www.cnblogs.com/fenice/p/5369824.html
可以建模为01背包的模型。
- f[i][j]f[i][j]f[i][j]表示前i个数的任意组合中gcdgcdgcd等于jjj的组合的种类数。
- 转移方程有:
- 第i个数不取:f[i][j]+=f[i−1][j]f[i][j]+=f[i-1][j]f[i][j]+=f[i−1][j];
- 第i个数要取:f[i][gcd(a[i],j)]+=f[i−1][j]f[i][gcd(a[i],j)]+=f[i-1][j]f[i][gcd(a[i],j)]+=f[i−1][j];
可以离线处理出1000以内任意两个数的gcd值,否则会超时;
当然也可以通过减枝来降低时间复杂度(如果