洛谷 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 
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<
			if(j%2==0) sum+=(i/j);
			else sum+=-(i/j);
//			cout<
		}		
	}
	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 
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;
}

你可能感兴趣的:(luogu_topic,算法)