cf434 div.2 A. k-rounding

本文介绍了一种求解两个数n和10^k最小公倍数的算法实现,通过计算最大公约数来简化计算过程,适用于数学竞赛及算法初学者。

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

原题

求n和10^k的最小公倍数;

n*10^k/gcd(n,10^k);

#include<cstdio>
using namespace std;
long long gcd(long x,long y)
{
    return (y==0)?x:gcd(y,x%y);
}
int main()
{
    long long n;
    int k;
    scanf("%lld%d",&n,&k);
    long long sum=1;
    for(int i=1;i<=k;i++)
        sum=sum*10;
    printf("%lld",sum*n/gcd(sum,n));
    return 0;
}

<think>我们使用`Map.computeIfAbsent`方法时,通常是为了在键不存在时计算一个新值并放入Map。然而,用户的需求是进行累加操作(即更新现有值),而`computeIfAbsent`只会在键不存在时起作用。对于累加操作,更合适的方法是使用`merge`方法,但用户明确要求使用`computeIfAbsent`。因此,我们可以这样考虑:先用`computeIfAbsent`来确保键存在(如果不存在则初始化为一个BigDecimal.ZERO),然后再使用其他方法(如`put`或`replace`)进行累加。但这样不是原子操作,在并发环境下不安全。另一种思路:使用`computeIfAbsent`初始化,然后使用`compute`或`replace`进行累加,但这样需要两次操作。实际上,对于累加操作,更推荐使用`merge`方法,因为它可以原子性地完成“如果不存在则初始化,如果存在则累加”的操作。但是,如果用户坚持要用`computeIfAbsent`,我们可以结合后续的累加操作,但需要注意线程安全。以下是一个示例:假设我们有一个`Map<String,BigDecimal>`,我们想对某个键进行累加。步骤:1.使用`computeIfAbsent`确保键存在,如果不存在则放入0。2.然后使用`put`或`replace`方法更新值(但这不是原子操作)。在非线程安全的环境下可以这样写:```javaMap<String,BigDecimal>map=newHashMap<>();Stringkey="someKey";BigDecimalvalueToAdd=newBigDecimal("10.5");//如果键不存在,则初始化为BigDecimal.ZEROmap.computeIfAbsent(key,k->BigDecimal.ZERO);//然后累加map.put(key,map.get(key).add(valueToAdd));```然而,这种方法在并发环境下不安全。如果要求线程安全,可以使用`ConcurrentHashMap`,但上述两步操作也不是原子的。因此,我们更推荐使用`merge`方法,它可以原子性地完成:```javamap.merge(key,valueToAdd,BigDecimal::add);```上面的代码意思是:如果键存在,则用BigDecimal::add函数将原值和传入值相加;如果键不存在,则直接放入传入值(注意:如果传入值不是我们想要的初始值,比如我们想初始化为0,那么我们可以先将传入的值设为要加的数,然后合并函数用加法,这样当不存在时就会放入这个数,但这样第一次放入的值就是valueToAdd,而不是0+valueToAdd。如果我们希望初始化为0,那么我们可以这样调整:先检查是否存在,不存在则初始化为0,然后再累加?)实际上,`merge`方法的第二个参数是当键不存在时放入的值,第三个参数是合并函数。所以如果我们希望当键不存在时,我们放入0,然后加上要加的数,那么我们可以:```java//但这样不行,因为merge的第二个参数是当键不存在时放入的值,我们想要的是0,然后再加上valueToAdd,但是这样就会变成0+valueToAdd=valueToAdd,所以等同于:map.merge(key,valueToAdd,(oldValue,newValue)->oldValue.add(newValue));```这实际上和直接放入valueToAdd然后存在时再相加是一样的。也就是说,如果键不存在,我们放入valueToAdd,如果存在,则加上valueToAdd。这符合累加的需求,因为第一次放入的就是valueToAdd,相当于0+valueToAdd。所以这样写是符合要求的。因此,我们推荐使用`merge`。但是,如果用户坚持使用`computeIfAbsent`,我们可以这样(非原子操作):```javamap.computeIfAbsent(key,k->BigDecimal.ZERO);map.put(key,map.get(key).add(valueToAdd));```或者使用`compute`方法(原子操作,但需要整个Map操作同步,或者使用ConcurrentMap的compute方法):```java//使用HashMap,非线程安全,需要外部同步synchronized(map){map.compute(key,(k,currentValue)->(currentValue==null)?valueToAdd:currentValue.add(valueToAdd));}```在ConcurrentHashMap中,我们可以使用`compute`方法(原子操作):```javaConcurrentMap<String,BigDecimal>map=newConcurrentHashMap<>();map.compute(key,(k,currentValue)->(currentValue==null)?valueToAdd:currentValue.add(valueToAdd));```但是,用户要求使用`computeIfAbsent`,那么我们可以利用它来初始化,然后用循环和CAS式操作(在ConcurrentHashMap中)来更新,但这样很复杂。因此,总结:对于累加操作,最佳实践是使用`merge`方法。如果一定要用`computeIfAbsent`,那么需要结合后续的更新操作,但要注意线程安全。所以,针对用户的问题,我们给出两种方案:方案一(推荐):使用`merge````javaMap<String,BigDecimal>map=newHashMap<>();//或者ConcurrentHashMapStringkey="key";BigDecimalvalueToAdd=newBigDecimal("100.00");//原子性累加(在ConcurrentHashMap中是原子的,在HashMap中不是,但可以外部同步)map.merge(key,valueToAdd,BigDecimal::add);```方案二:使用`computeIfAbsent`(非原子操作,适用于单线程)```javaMap<String,BigDecimal>map=newHashMap<>();Stringkey="key";BigDecimalvalueToAdd=newBigDecimal("100.00");//如果key不存在,初始化为0BigDecimaloldValue=map.computeIfAbsent(key,k->BigDecimal.ZERO);//然后更新,注意:这里直接更新oldValue并不会影响map中的值,因为BigDecimal是不可变的,所以需要重新放入map.put(key,oldValue.add(valueToAdd));```但是方案二中,我们更新map的操作是`put`,这可能会覆盖其他线程的更新。所以多线程环境下,应该使用方案一(配合ConcurrentHashMap)或者使用同步机制。因此,根据用户的具体场景选择。如果用户是在多线程环境下,且使用ConcurrentHashMap,那么使用`merge`是原子的。如果使用普通的HashMap,并且需要线程安全,则应该进行同步。另外,注意BigDecimal是不可变类,所以每次操作都会生成新的对象。最后,回答用户的问题:如何使用computeIfAbsent实现累加?我们可以用computeIfAbsent来初始化,然后再用put更新,但这不是原子操作。因此,我们更推荐使用merge方法,因为它简洁且可以原子操作(在支持并发的Map中)。如果用户坚持使用computeIfAbsent,那么代码示例如上(方案二)。下面我们给出一个完整的示例:</think>要使用 Java Map 的 `computeIfAbsent` 方法对 `BigDecimal` 值进行累加操作,可以结合 `computeIfAbsent` 的初始化和后续的累加逻辑。以下是实现方法和最佳实践: ### 解决方案 ```java import java.math.BigDecimal; import java.util.HashMap; import java.util.Map; public class MapAccumulator { public static void main(String[] args) { // 创建 Map 存储键值对 Map<String, BigDecimal> amountMap = new HashMap<>(); // 要累加的值 BigDecimal increment = new BigDecimal("100.50"); String key = "account_123"; // 使用 computeIfAbsent 实现累加 amountMap.computeIfAbsent(key, k -> BigDecimal.ZERO); // 初始化 amountMap.compute(key, (k, current) -> current.add(increment)); // 累加 System.out.println(amountMap.get(key)); // 输出: 100.50 } } ``` ### 关键步骤解析 1. **初始化值**: ```java amountMap.computeIfAbsent(key, k -> BigDecimal.ZERO); ``` - 当键不存在时,自动初始化为 `BigDecimal.ZERO` - 确保后续累加操作不会因 `NullPointerException` 中断[^1] 2. **安全累加**: ```java amountMap.compute(key, (k, current) -> current.add(increment)); ``` - 使用 `compute` 方法原子性地更新值 - `current.add(increment)` 执行精确的 `BigDecimal` 加法[^1] ### 线程安全版本(使用 ConcurrentHashMap) ```java import java.math.BigDecimal; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public class ConcurrentAccumulator { public static void main(String[] args) { ConcurrentMap<String, BigDecimal> concurrentMap = new ConcurrentHashMap<>(); BigDecimal increment = new BigDecimal("75.25"); String key = "user_456"; // 单步原子操作:初始化 + 累加 concurrentMap.merge(key, increment, BigDecimal::add); System.out.println(concurrentMap.get(key)); // 输出: 75.25 } } ``` - `merge()` 方法更简洁,在并发环境下安全高效 - 语义:`若key不存在 → 存入increment;若存在 → 执行BigDecimal::add` ### 性能对比 | 方法 | 线程安全 | 代码简洁性 | 执行效率 | |---------------------|----------|------------|----------| | `computeIfAbsent`+`compute` | 需额外同步 | 中等 | 中等 | | `merge` | 是(ConcurrentHashMap) | 高 | 高 | | 传统 `get`/`put` | 否 | 低 | 低 | ### 实际应用场景 ```java // 交易流水累加器 public class TransactionProcessor { private final Map<String, BigDecimal> ledger = new HashMap<>(); public void processTransaction(String accountId, BigDecimal amount) { ledger.computeIfAbsent(accountId, k -> BigDecimal.ZERO); ledger.compute(accountId, (k, bal) -> bal.add(amount)); } public BigDecimal getBalance(String accountId) { return ledger.getOrDefault(accountId, BigDecimal.ZERO); } } ``` ### 注意事项 1. **不可变对象**: - `BigDecimal` 是不可变类,每次运算都返回新对象 - 必须通过 `put` 或 `compute` 更新 Map 中的引用 2. **精度控制**: ```java // 累加时指定精度和舍入模式 map.compute(key, (k, current) -> current.add(increment).setScale(2, RoundingMode.HALF_UP) ); ``` 3. **空值处理**: - `computeIfAbsent` 的映射函数不能返回 `null`,否则抛 `NullPointerException` - 始终返回有效的 `BigDecimal` 实例(如 `BigDecimal.ZERO`) > 推荐优先使用 **`merge` 方法**,它在 ConcurrentHashMap 中提供原子操作,代码更简洁高效。传统 `computeIfAbsent`+`compute` 方案适用于非并发场景[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值