hdu 5656 CA Loves GCD(dp+gcd)(Bestcoder #78 1002)

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 535    Accepted Submission(s): 188


Problem Description
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.
 

Input
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].
1T50
 

Output
T lines, each line prints the sum of GCDs mod 100000007.
 

Sample Input
2 2 2 4 3 1 2 3
 

Sample Output
8 10
 

Source
 

Recommend
wange2014
 


題目大意:

       給定一個序列a,從中取出若干個數字求gcd,求解所有抽取方案的gcd之和

解題思路:

      dp[i][j]表示序列a從0到i的數中,取出的gcd爲j的方案數。那麼對於每個i,dp[i+1][j]由三部分組成,選a[i+1]也選擇前面的,只選a[i+1],只選前面的,所以有:

      dp[i+1][j]=sigema(dp[i][m])(滿足gcd(m,a[i+1])=j,m>=1&&m<=1000)

                        +dp[i][j]

                       +(a[i]==j)

      最後的ans=sigema(dp[n-1][j]*j)(滿足j>=1&&j<=1000)

p.s.:1.求解gcd(m,a[i+1])=j的數的時候,如果直接遍歷會T,要先預處理,找到每一個和a[i+1]/j互素的數字,把他乘上j就是m

           2.dp數組別忘了可能超過int,要用ll+取摸

           3.題幹中說的不同方案其實是一個方案中有一個數下標和另一個方案裏中不同就可以

<pre name="code" class="cpp">#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
#define ll long long
#define INF 0x3f3f3f3f
#define C(a) memset(a,0,sizeof a)
#define C_1(a) memset(a,-1,sizeof a)
#define C_i(a) memset(a,0x3f,sizeof a)
#define F(i,n) for(int i=0;i<n;i++)
#define F(n) for(int i=0;i<n;i++)
#define F_1(n) for(int i=n;i>0;i--)

#define S(a) scanf("%d",&a);
#define S2(a,b) scanf("%d%d",&a,&b);
#define SL(a) scanf("%I64d",&a);
#define SD(a) scanf("%lf",&a);
#define P(a) printf("%d\n",a);
#define PL(a) cout<<a<<endl;
#define PD(a)printf("%lf\n",a);

#define rush() int t;scanf("%d",&t);while(t--)
#define mod 100000007
using namespace std;

vector<int>v[1005];
ll dp[1005][1005];
int a[1005];;
int gcd(int a, int b)
{
	while (a&&b)
	{
		if (a > b)a = a%b;
		else b = b%a;
	}
	return a + b;
}
void init()
{
	for (int i = 1; i < 1005; i++)
		for (int j = 1; j <1005; j++)
			if (gcd(i, j) == 1)v[i].push_back(j);
}
int main()
{
	ll ans = 0;
	init();
	rush()
	{
		ans = 0;
		C(a); C(dp);
		int n, tem;
		S(n);
		for (int i = 0; i < n; i++)S(a[i]);
		dp[0][a[0]] = 1;
		for (int i = 1; i < n; i++)
			for (int j = 1; j <= 1000; j++)
			{
				ll cnt = dp[i - 1][j] + (a[i] == j);
				int k = 2;
				if (!(a[i] % j))
				{
					int tem=a[i]/j;
					for (int k = 0; k < v[tem].size()&&j*v[tem][k]<1005; k++)
						cnt = (dp[i - 1][j*v[tem][k]]+cnt)%mod;
				}//不預處理會超時
				dp[i][j] = cnt;
			}
		for (int i = 1; i <= 1000; i++)ans = (ans + i*dp[n - 1][i]) % mod;
		PL(ans);
	}
}



發佈了43 篇原創文章 · 獲贊 8 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章