HDU 5656 CA Loves GCD
2016-05-21 20:48
330 查看
CA Loves GCD
[b]Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1730 Accepted Submission(s): 550
[/b]
[align=left]Problem Description[/align]
CA is a fine comrade who loves the party and people; inevitably she loves GCD (greatest common divisor) too.
Now, there are N
different numbers. Each time, CA will select several numbers (at least one), and find the GCD of these numbers. In order to have fun, CA will try every selection. After that, she wants to know the sum of all GCDs.
If and only if there is a number exists in a selection, but does not exist in another one, we think these two selections are different from each other.
[align=left]Input[/align]
First line contains T
denoting the number of testcases.
T
testcases follow. Each testcase contains a integer in the first time, denoting
N,
the number of the numbers CA have. The second line is
N
numbers.
We guarantee that all numbers in the test are in the range [1,1000].
1≤T≤50
[align=left]Output[/align]
T
lines, each line prints the sum of GCDs mod 100000007.
[align=left]Sample Input[/align]
2
2
2 4
3
1 2 3
[align=left]Sample Output[/align]
8
10
[align=left]Source[/align]
BestCoder Round #78 (div.2)
[align=left]Recommend[/align]
wange2014 | We have carefully selected several similar problems for you: 5694 5693 5692 5689 5687
题意:n个数里面任意挑选几个数出来,求剩下的数的gcd之和。因为范围在1000之间,我们可以计算出gcd为1到1000的所有方案数。
令dp[i][j]代表选了前i个数 gcd为j的方案数。选i+1个数转移为dp[i][j]+=dp[i+1][f[j][a[i+1]]] 。不选为dp[i][j]+=dp[i+1][j];其中f[i][j]代表i,j两数的gcd
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long LL;
int f[1001][1001];
int dp[1001][1001];
int a[1001];
const int mod=100000007;
inline void add(int b,int &a)
{
if((a+=b)>=mod)a-=mod;
}
int main()
{
int t;
int i,j;
for(i=0; i<=1000; i++)
for(j=0; j<=1000; j++)
f[i][j]=__gcd(i,j);
scanf("%d",&t);
while(t--)
{
int n;
cin>>n;
memset(a,0,sizeof(a));
for(i=1; i<=n; i++)
cin>>a[i];
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(i=0; i<n; i++)
for(j=0; j<=1000; j++)
{
if(dp[i][j])
add(dp[i][j],dp[i+1][j]);
add(dp[i][j],dp[i+1][f[j][a[i+1]]]);
}
LL ans=0;
for(i=1; i<=1000; i++)
ans+=LL (i)*dp
[i];
printf("%lld\n",ans%mod);
}
return 0;
}
相关文章推荐
- 递归
- 中国剩余定理的解析及记忆(扩展欧几里得算法的运用)
- 素数表的快速建立,合数分解,1-2^31内某个长度小于10w的区间素数筛选的三个模板及解析
- 线段树3种基础模型的理解和记忆(任意区间求和,任意区间的所有数加上相同数(懒操作),任意区间所有数变成同一个值再求和)
- ZOJ 1610 Count the Colors 多次更新一次查询,只需要一一标记
- POJ 3264 Balanced Lineup 查询区间最大最小值 基础线状树水题
- HDU 1698 Just a Hook 线状树经典模型之区间变动bool标记,上下同时更新
- POJ 3468 A Simple Problem with Integers(线状树经典模型之lazy操作)
- POJ 2251 Dungeon Master 比较有趣的三维迷宫bfs搜索路径
- 论Acmer的自我修养 (算法学习目标和推荐题目)
- HDU 1260 Tickets (很简单的基础DP题,找到状态转移方程就直接AC了)
- HDU 1176 免费馅饼 (类似于数塔DP的题目,注意边界条件,细节处理)
- HDU 1114 Piggy-Bank (完全背包水题,但注意一下时间输出)
- HDU 1087 Super Jumping!Jumping!Jumping求连续上升子序列的最大和值 (解析)
- HDU 1069 Monkey and Banana 对比优先权的设置和排序问题(解析)
- HDU 1029 Ignatius and the Princess IV(动规水题,有个很精妙的快解法)
- HDU 1024 Max Sum Plus Plus求前n个数中的若干个数分为连续的m段的最大和值(解析)
- HDU2000
- HDU2003
- HDU1095