洛谷 T422589 sum(求和)

题意

给定A,B。求值
∑ i = A B ∑ i j = 1 ⌊ i j ⌋ × ( − 1 ) j \sum_{i=A}^{B}\sum_{i}^{j=1}\left \lfloor \frac{i}{j} \right \rfloor \times (-1)^ {j} i=ABij=1ji×(1)j

数据规模与约定

对于 50 % 50\% 50% 的数据: 1 ≤ A ≤ B ≤ 5 × 1 0 3 1\le A\le B\le 5\times 10^{3} 1AB5×103
对于 70 % 70\% 70% 的数据: 1 ≤ A ≤ B ≤ 5 × 1 0 4 1\le A\le B\le 5\times 10^{4} 1AB5×104
对于 100 % 100\% 100% 的数据: 1 ≤ A ≤ B ≤ 2 × 1 0 7 1\le A\le B\le 2\times 10^{7} 1AB2×107

50分思路

1.解析题意,可以得到一串暴力代码
code↓

#include <bits/stdc++.h>
using namespace std;
long long a,b;
long long f(long long x,long long y){
	long long sum=0;
	for(int i=a;i<=b;i++){
		for(int j=1;j<=i;j++){
//	   	    cout<<i<<" "<<j<<" "<<i/j<<" "<<sum<<" ";
			if(j%2==0) sum+=(i/j);
			else sum+=-(i/j);
//			cout<<sum<<endl;			
		}		
	}
	return sum;
}
int main(){
	// freopen("sum.in","r",stdin);
	// freopen("sum.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin>>a>>b;
	cout<<f(a,b); 
	return 0;
}

70分思路

1.通过暴力打表找规律题意中的向下取整可得 i / j 向下取整 中必定是有重复的,而 (-1)^j则说明了当 j j j奇数时这个数便是负数,而当 j j j偶数时这个数便是正数

我们来看一串数字:

 i  j i/j   sum  正负性
99 19  5  -67 -72 -
99 20  4  -72 -68 +
99 21  4  -68 -72 -
99 22  4  -72 -68 +
99 23  4  -68 -72 -
99 24  4  -72 -68 +
99 25  3  -68 -71 -
//sum有两个,因为前一个是sum进行变化前的,后一个是sum进行变化后的

从上述的数字中我们可以发现,其中的i/j是重复的,但是怎么计算他们这串数字的值呢?
这串数字具有正负性,我们可以总结出一个规律

1   2  3  4  5  6  7  8 vis 
-1 +1 -1 +1 -1 +1 -1 +1 val
start num end
1      0   0
1      1  -1
0      0   0
0      1   1
//其中的0代表偶数,1代表奇数。
//start代表开始的数的奇偶性,num代表总共的个数的奇偶性,end代表结果的奇偶性

这串规律就是当个数偶数时结果一定为偶数个数相加,因为它的值是相同的,所以偶数个数相加的结果为0
个数奇数时:
如果开始的那个数为奇数,那结果就应该减去现在的值,也就是-(i/j)
如果开始的那个数为偶数,那结果就应该加上现在的值,也就是+(i/j)

code↓

#include <bits/stdc++.h>
using namespace std;
long long a,b;
long long f(long long x,long long y){
	long long sum=0;
	for(int i=a;i<=b;i++){
	    long long val=i,vis=1;//val表示现在的值,vis表示现在的编号,也就是上述的start
	    while(1){
			long long sum1=0,bj=i/val,num=bj-vis+1;	//sum1是当前区间的和
			if(num%2!=0){//,bj是结束的数的编号,num是整个区间的个数
				if(vis%2==0) sum1+=val;
				else sum1-=val; 
			}
			vis=vis+num;
			val=i/vis;
			sum+=sum1;
			if(vis==i+1) break;//因为是直接加的num,所以会是i+1
	    }
	}
	return sum;
}
int main(){
//	freopen("sum.in","r",stdin);
//	freopen("sum.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin>>a>>b;
	cout<<f(a,b); 
	return 0;
}
  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花火Spark

鼓励,如星光,照亮我创作的前路

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值