牛客练习赛53——B.美味果冻

本文分享了一道ACM竞赛题目的解题思路,通过巧妙的数学变换优化算法,将原本难以解决的问题转化为易于编程的形式。文章详细解释了如何通过交换求和顺序,将复杂度降低,并利用快速幂和数列公式进行高效计算。
部署运行你感兴趣的模型镜像

前言
又是一个只过了签到题的比赛,蒟蒻又来补题了。
在这里插入图片描述

题目链接

https://ac.nowcoder.com/acm/contest/1114/B
在这里插入图片描述

题目理解

蒟蒻看到这一题就想用暴力做,无奈n很大,暴力只会超时。做的时候想过将 ∑ i = 1 n \sum_{i=1}^{n} i=1n ∑ j = 1 i \sum_{j=1}^{i} j=1i变换一下,但是蒟蒻太菜了,于是愉快的等到比赛结束去看题解。题解里果然是交换成 ∑ j = 1 n \sum_{j=1}^{n} j=1n ∑ i = j n \sum_{i=j}^{n} i=jn,为什么可以这样交换可以看下面的图。把两个式子看成同一个下三角矩阵就行了,两个是一摸一样的。
在这里插入图片描述

  • 对原式 ∑ i = 1 n ∑ j = 1 i i ∗ ( ⌈ i j ⌉ ) j \sum_{i=1}^{n}\sum_{j=1}^{i}i\ast (\left \lceil \frac{i}{j} \right \rceil)^{j} i=1nj=1ii(ji)j来说, j在内循环而且它还是指数,很不好写程序,要考虑的东西很多。但是交换一下顺序就不同了。
  • 换成 ∑ j = 1 n ∑ i = j n i ∗ ( ⌈ i j ⌉ ) j \sum_{j=1}^{n}\sum_{i=j}^{n}i\ast (\left \lceil \frac{i}{j} \right \rceil)^{j} j=1ni=jni(ji)j后,j在外层,那么对于内循环来说只需要考虑i作为变量,把i与 ( ⌈ i j ⌉ ) j (\left \lceil \frac{i}{j} \right \rceil)^{j} (ji)j分开计算即可。
  • 考虑n很大,可以采用更快速的方法,这里我们找 ( ⌈ i j ⌉ ) j (\left \lceil \frac{i}{j} \right \rceil)^{j} (ji)j的规律。

打表如下
在这里插入图片描述
可以看出 ( ⌈ i j ⌉ ) j (\left \lceil \frac{i}{j} \right \rceil)^{j} (ji)j可以把n分成 n j \frac{n}{j} jn块,然后每一块的分别算幂,用快速幂也会超时,所以需要用数组模拟每一块的幂。对于计算i可以用每一块长度的等差求和公式来计算。但是对于长度不满 n j \frac{n}{j} jn的块来说,需要处理一下单独的长度就行了。

AC代码
//思维+分块+模拟快速幂+取模+数列公式 
#include<iostream>
#define int long long
using namespace std;
const int maxn = 3e7 +10;
const int mod = 1e9+7;
signed main(){
	int n;
	scanf("%lld",&n);
	int prime[maxn];
	fill(prime,prime+n+1,1);
	int ans=0;
	for(int j=1;j<=n;j++){
		int k=n/j;
		int l=j;
		int r=j+j-1;
		for(int i=1;i<k;i++){
			prime[i]=1LL*prime[i]*i%mod;   
			ans=(ans+(1LL*((r+l)*j/2%mod)*prime[i]%mod))%mod;
			l+=j;
			r+=j;
		}
		prime[k]=1LL*prime[k]*k%mod;
		ans=(ans+1LL*(l+n)*(n-l+1)/2%mod*prime[k]%mod)%mod;
	}
	printf("%lld",ans);
	return 0;
}

您可能感兴趣的与本文相关的镜像

Seed-Coder-8B-Base

Seed-Coder-8B-Base

文本生成
Seed-Coder

Seed-Coder是一个功能强大、透明、参数高效的 8B 级开源代码模型系列,包括基础变体、指导变体和推理变体,由字节团队开源

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值