数论——HDU 4961

对应HDU题目:点击打开链接

Boring Sum

Time Limit: 1000MS   Memory Limit: 131072KB   64bit IO Format: %I64d & %I64u

[Submit]  
[Go Back]   [Status]

Description

Number theory is interesting, while this problem is boring.

Here is the problem. Given an integer sequence a 1, a 2, …, a n, let S(i) = {j|1<=j<i, and a j is a multiple of a i}. If S(i) is not empty, let f(i) be the maximum integer in S(i); otherwise, f(i) = i.
Now we define b&#31;i as a f(i). Similarly, let T(i) = {j|i<j<=n, and a j is a multiple of a i}. If T(i) is not empty, let g(i) be the minimum integer in T(i); otherwise, g(i) = i. Now we define &#31;c i as ag(i).
The boring sum of this sequence is defined as b 1 * c 1 + b 2 * c 2 + … + b n * c n.

Given an integer sequence, your task is to calculate its boring sum.

Input

The input contains multiple test cases.

Each case consists of two lines. The first line contains an integer n (1<=n<=100000). The second line contains n integers a 1, a2, …, a n (1<= a i<=100000).

The input is terminated by n = 0.

Output

Output the answer in a line.

Sample Input

 5
1 4 2 3 9
0 

Sample Output

 136 

题意:对每个a[i],找a[i]往左第一个是a[i]倍数的数a[j],记b[i]=a[j],如没有就b[i]=a[i],

对每个a[i],找a[i]往右第一个是a[i]倍数的数a[j],记c[i]=a[j],如没有就c[i]=a[i];之后把

所有b[i]*c[i]相加,输出结果。

思路:从左往右扫a[],用数组yin[]下标表示a[i]因子,如扫到a[2]=4时,yin[1]=yin[2]=yin[4]=a[2];

这样扫到a[3]=2时;如yin[a[3]]!=0,则b[3]=yin[a[3]],否则b[3]=a[3].求c[]就把yin[]清零后从右往左

扫a[]。

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
const int MAXN=100000+10;
#define ms(x,y) memset(x,y,sizeof(x))
using namespace std;
int a[MAXN];
int b[MAXN];
int c[MAXN];
int yin[MAXN];

void cal(int x)
{
	for(int i=1; i*i<=x; i++)
		if(x%i==0){yin[i]=yin[x/i]=x;}
}

int main()
{
	//freopen("in.txt","r",stdin);
	int n;
	while(scanf("%d", &n), n)
	{
		ms(yin,0);
		ms(b,0);
		ms(c,0);
		int i;
		for(i=1; i<=n; i++) scanf("%d", a+i);
		for(i=1; i<=n; i++){
			if(yin[a[i]]) b[i]=yin[a[i]];
			else b[i]=a[i];
			cal(a[i]);
		}
		ms(yin,0);
		for(i=n; i>=1; i--){
			if(yin[a[i]]) c[i]=yin[a[i]];
			else c[i]=a[i];
			cal(a[i]);
		}
		long long sum=0;
		for(i=1; i<=n; i++)
			sum+=(long long)b[i]*c[i];
		printf("%I64d\n",sum);
	}
	return 0;
}
时间: 2024-11-09 02:29:50

数论——HDU 4961的相关文章

hdu 4961 数论 o(nlogn)

Boring Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 60    Accepted Submission(s): 30 Problem Description Number theory is interesting, while this problem is boring.   Here is the probl

HDU - 4961 Boring Sum

Problem Description Number theory is interesting, while this problem is boring. Here is the problem. Given an integer sequence a1, a2, -, an, let S(i) = {j|1<=j<i, and aj is a multiple of ai}. If S(i) is not empty, let f(i) be the maximum integer in

hdu 4961 Boring Sum(高效)

题目链接:hdu 4961 Boring Sum 题目大意:给定ai数组; 构造bi, k=max(j|0<j<i,aj%ai=0), bi=ak; 构造ci, k=min(j|i<j≤n,aj%ai=0), ci=ak; 求∑i=1nbi?ci 解题思路:因为ai≤105,所以预先处理好每个数的因子,然后在处理bi,ci数组的时候,每次遍历一个数,就将其所有的因子更新,对于bi维护最大值,对于ci维护最小值. #include <cstdio> #include <c

HDU 4961 Boring Sum 暴力

题意:对于所有的A[I],同时找到左边和右边离它最近且是它的倍数的数相乘最后加起来求和. 解题思路:n*sqrt(n)的算法,开始以为过不了,wa了两发因为lld I64d对拍一个小时发现一个小时前交的代码没错只是没变I64d,..具体思路是枚举每个a[i]的因子,找离它最近的那个更新,如果已经没更新就不用更新了.用两个辅助数组记录最近的就行. 解题代码: 1 // File Name: 1002.cpp 2 // Author: darkdream 3 // Created Time: 201

HDU 4961 Boring Sum 构造题

用一个数组c, c[i]表示i这个数出现的最近数字是几. 那么当加入一个6,则 c[1] = c[2] = c[3] = c[6] = 6; ==最近怎么都要开挂啊.. #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N = 100005; inl

2014多校训练九(HDU 4960 HDU 4961 HDU 4965 HDU 4968 HDU 4969 HDU 4970)

HDU 4960 Another OCD Patient 题意:给你一串数字  相邻x个数字合并成一个数字(相加)有一定代价  问  最少花费多少使得串变成回文串 思路: 读完题感觉像dp  数据范围也像  就开始想怎么表示状态  最简单的应该想到dp[i][j]表示i到j区间变成回文串的最小花费  状态想好了想做法  考虑将串分成AAAABBBBBBBCCC三段  即所有A合成一个数字  C也是  而且A和C相等  那么B串就变成了子问题  但是A和C是不是都要枚举呢?  这个串所有元素都是正

hdu 4961 数学杂题

http://acm.hdu.edu.cn/showproblem.php?pid=4961 先贴个O(nsqrtn)求1-n所有数的所有约数的代码: vector<int>divs[MAXN]; void caldivs() { for(int i=1;i<MAXN;i++) for(int j=i;j<MAXN;j+=i) divs[j].push_back(i); } 有了这个当时理下思路就可写了,但是重复数处理注意: 1.用一个数组vis[]  vis[i]=1表示i存在

HDU 4961(杭电多校#9 1002题)Boring Sum(瞎搞)

题目地址:HDU 4961 看来这题的测试数据是随机的.不然出了极限数据还真过不了...这题我的方法是建一个哈希结构体,记录两个变量,分别是num位置,然后是f,f==0表示这个数没出现过,f==1表示这个数出现过.然后分别从前面和后面扫一遍.每次扫的时候,对每一个出现的数都进行标记.然后对当前的数枚举该数的倍数,全部枚举完,取位置num最大的.然后找完之后,对哈希结构体进行更新.如果前面曾经出现过的话,就直接换掉,因为后面的数总比前面的更优.最后扫完两遍之后两个数组就能求出来了.计算就行了.

HDU 4961 Boring Sum 打表、更新

点击打开链接 Boring Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 715    Accepted Submission(s): 351 Problem Description Number theory is interesting, while this problem is boring. Here is th