HDU 5656 CA Loves GCD 01背包+gcd

本文介绍了一道经典的算法竞赛题目——GCD组合求和问题,该问题要求计算从N个不同整数中选取任意数量的数进行组合,求出所有可能组合的GCD(最大公约数)之和。文章提供了详细的解析过程,采用01背包模型解决,并通过离线预处理任意两数的GCD来优化时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:

hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5656

bc:http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=683&pid=1002

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 10001≤T≤50, 1≤N≤1000, 1≤Ai​​≤1000

输出描述

对于每组数据输出一行一个整数表示CA所有的选法的GCD的和对100000007100000007取模的结果。

输入样例

2

2

2 4

3

1 2 3

输出样例

8

10

题解:

  可以建模为01背包的模型。

  dp[i][j]表示前i个数的任意组合中gcd等于j的组合数。

  转移方程有:(刷表法)

    第i个数不取:dp[i][j]+=dp[i-1][j];

    第i个数要取:dp[i][gcd(a[i],j)]+=dp[i-1][j];

  可以离线处理出1000以内任意两个数的gcd值,否则会超时,当然也可以通过减枝来降低时间复杂度(如果dp[i-1][j]=0,就没必要算gcd(a[i],j)了)。

  初始化有dp[0][0]=1(一个数都没有,则有gcd为0)




#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

typedef long long LL;
const int maxn = 1000 + 10;
const int mod = 1e8 + 7;//这里不要写成1e9+7!!!!

int n;
int a[maxn], dp[maxn][maxn];
int g[maxn][maxn];

int gcd(int a, int b) {
    return b == 0 ? a : gcd(b, a%b);
}

void get_g() {
    for (int i = 0; i <= 1000; i++) {
        for (int j = i; j <= 1000; j++) {
            g[i][j] = g[j][i] = gcd(i, j);
        }
    }
}

void init() {
    memset(dp, 0, sizeof(dp));
}

int main() {
    get_g();
    int tc;
    scanf("%d", &tc);
    while (tc--) {
        init();
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d", a + i);
        }
        dp[0][0] = 1;
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= 1000; j++) {
                dp[i][j] += dp[i - 1][j]; dp[i][j] %= mod;

                int tmp = g[a[i]][j];
                dp[i][tmp] += dp[i - 1][j]; dp[i][tmp] %= mod;
            }
        }
        LL ans = 0;
        for (int i = 1; i <= 1000; i++) {
            ans += (LL)dp[n][i] * i;
            ans %= mod;
        }
        printf("%lld\n", ans);
    }
    return 0;
}


资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值