題意:
給n個不同的數,求所有非空子集的gcd之和
思路:
dp[ i ] 表示 gcd 爲 i 的子集數
每讀入一個新的數x,可以如果將x與gcd爲i的放在一起會導致gcd(x,i)的方案數增加dp[ i ] 種
如果 i = x,那麼還會額外多一種方案(只放x)。
因爲 較小的gcd(x,i)可能會用到同階段的較大的 i ,所有操作順序要從小到大。
代碼:
#include<bits/stdc++.h>
const long long mod = 1e8+7;
using namespace std;
const int N = 1005;
int dp[N];
int main()
{
int T;
scanf("%d",&T);
while(T--){
memset(dp,0,sizeof(dp));
int n,x,m = 0;
scanf("%d",&n);
while(n--){
scanf("%d",&x);
m = max(m,x);
for(int i=1;i<=m;i++){
if(i==x)dp[i] = ( ( dp[i]*2 ) + 1 ) % mod;
else if(dp[i]){
int j = __gcd(i,x);
dp[j] = (dp[j] + dp[i]) % mod;
}
}
}long long ans =0;
for(int i=1;i<=m;i++){
ans = (ans + 1LL * i * dp[i] % mod)% mod;
}printf("%I64d\n",ans);
}return 0;
}