Sum HDU - 4407

本文介绍了一道名为HDU4407的算法题目解析,该题涉及序列操作,包括区间内与特定数互质数值之和的查询及数值修改。文章详细解释了解题思路,利用容斥原理及其变形来简化计算过程,并提供了完整的C++代码实现。

Sum(HDU 4407)

XXX is puzzled with the question below:

1, 2, 3, ..., n (1<=n<=400000) are placed in a line. There are m (1<=m<=1000) operations of two kinds.

Operation 1: among the x-th number to the y-th number (inclusive), get the sum of the numbers which are co-prime with p( 1 <=p <= 400000).
Operation 2: change the x-th number to c( 1 <=c <= 400000).

For each operation, XXX will spend a lot of time to treat it. So he wants to ask you to help him.

Input

There are several test cases. 

The first line in the input is an integer indicating the number of test cases.

For each case, the first line begins with two integers --- the above mentioned n and m.
Each the following m lines contains an operation.
Operation 1 is in this format: "1 x y p".
Operation 2 is in this format: "2 x c".

Output

For each operation 1, output a single integer in one line representing the result.

Sample Input
1
3 3
2 2 3
1 1 3 4
1 2 3 6
Sample Output
7
0

题意:

一个长度为n的序列,开始的序列为1,2,3....n;

然后又两种操作。

operation1: 询问区间[a,b]中与p互质的数的和。

operation2:将序号为i的数修改为x;

如果没有修改操作,那么狠明显就是一个容斥原理

计数的问题。

分析:刚开始看题的时候,理解错了题意,耽误了很多时间,对于操作一,要求的是区间中与p互质数的和,就是区间中与p互质的数加起来。因为在进行操作二之前,这样的区间是等差数列,所以可先出这个区间所有数的和,然后减去与p不互质的数的和,就是所求的结果(这里用到了容斥原理的变形),对p进行素因子分解,不符合条件的数就是这些素因子的倍数的和,对于每一次操作,
sum=k*1+k*2+k*3+。。。。+k*m(其中k*m<=b&&k(m+1)>=b).

  这里用到了map,map既保存了未修改前的数,又保存了修改之后的数,具有对应关系。。至于修改,由于修改次数比较小,把修改存起来,对于每个查询,一个个改过去。



#include<cstdio>
#include<vector>
#include<iostream>
#include<map>
using namespace std;
vector<int>x;
map<int,int>Map;
void getPrimeFactor(int n)///对n进行素因子的分解
{                         ///容斥原理的必须步骤
    x.clear();
    for(int i=2;i*i<=n;i++)
        if(n%i==0)
    {
        x.push_back(i);
        while(n%i==0)
            n/=i;
    }
    if(n!=1)
        x.push_back(n);
}
bool gcd(int a,int b)///判断两个数是否互质
{                    ///互质返回true;否则返回false;
    while(b)
    {
        int t=a;
        a=b;
        b=t%b;
    }
    if(a==1)
        return true;
    else
        return false;
}
long long solve(int b,int p)///容斥原理的简单变形,要求的不是互质的个数
{                           ///而是互质数的和
    long long ans=(long long)b*(1+b)/2;
    long long sum=0;
    for(int i=1;i<(1<<x.size());i++)
    {
        int cnt=0;
        long long k=1;
        for(int j=0;j<x.size();j++)
            if(i&(1<<j))
        {
            cnt++;
            k*=x[j];
        }
        k=(b/k)*(k+(b/k)*k)/2;
        if(cnt&1)
            sum+=k;
        else
            sum-=k;
    }
    return ans-sum;
}
long long sub(long long ans,int a,int b,int p)///修改
{
    map<int,int>::iterator it;
    for(it=Map.begin();it!=Map.end();it++)
    {
        int f1=gcd(p,it->second);
        int f2=gcd(p,it->first);
        if(it->first<=b&&it->first>=a)
        {
            if(f1) ans+=it->second;
            if(f2) ans-=it->first;
        }
    }
    return ans;
}
int main()
{
    int t;
    cin>>t;
    int n,m;
    while(t--)
    {
        Map.clear();
        scanf("%d%d",&n,&m);
        int x,y,p;
        while(m--)
        {
            scanf("%d",&x);
            if(x==1)
            {
                scanf("%d%d%d",&x,&y,&p);
                getPrimeFactor(p);
                cout<<sub(solve(y,p)-solve(x-1,p),x,y,p)<<endl;
            }
            else
            {
                scanf("%d%d",&x,&p);
                Map[x]=p;
            }
        }
    }
    return 0;
}


### HDU 4190 编程问题解析 针对HDU-4190这一特定编程挑战,该题目属于动态规划(DP)类问题[^3]。这类问题通常涉及寻找最优路径或者计算最优化的结果,在给定约束条件下实现目标最大化或最小化。 对于此题目的具体描述提到的是一个数塔结构,其中要求从顶部到底部移动,并且每次只能前往相邻节点,最终目的是使得所经过节点数值总和达到最大值。解决此类问题的关键在于理解如何有效地利用已知条件来构建解决方案: #### 动态规划算法设计 为了高效求解这个问题,可以采用自底向上的方法来进行动态规划处理。通过定义状态转移方程,逐步累积中间结果直至获得全局最优解。 ```python def max_sum_path(triangle): n = len(triangle) # 初始化dp数组用于存储各层的最大累加和 dp = [[0]*i for i in range(1, n+1)] # 设置起点即三角形顶端元素作为初始值 dp[0][0] = triangle[0][0] # 填充dp表 for level in range(1, n): for pos in range(level + 1): if pos == 0: dp[level][pos] = dp[level - 1][pos] + triangle[level][pos] elif pos == level: dp[level][pos] = dp[level - 1][pos - 1] + triangle[level][pos] else: dp[level][pos] = max(dp[level - 1][pos], dp[level - 1][pos - 1]) + triangle[level][pos] return max(dp[-1]) triangle = [ [2], [3, 4], [6, 5, 7], [4, 1, 8, 3] ] print(max_sum_path(triangle)) ``` 上述代码实现了基于输入参数`triangle`(表示数塔的数据结构)的函数`max_sum_path()`,它返回从顶至底所能得到的最大路径和。这里采用了二维列表形式保存每一级的最佳选择情况,从而保证能够快速访问并更新所需的信息。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值