http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1008&cid=832
https://codeforces.com/contest/1062/problem/D
Problem Description
In the world line 1.048596%
今天的理科实验室依旧回响着气泡的大合唱。
梓川咲太一边看应考的题目一边听着声音的变化,同时思索该如何回答考察数学思维的题目......
就算解决了牧之原翔子和樱岛麻衣的问题,也终究要面对现实的考验。
“梓川你不是要和樱岛麻衣前辈考同一个大学吗?”
双叶理央坐在咲太的面前,今天也依然披着白大褂,正在准备不知名的实验。
“是啊。之前不是说过吗?所以我现在忙于备考。”
“我就友善的提醒你一句...”
“什么?”
“你看的是我的算法竞赛书......”双叶理央用略带担忧的声音这么说着。
梓川咲太突然回过神来,他翻了翻书本后面的内容,的确是和程序有关。但是前面的例题部分做的却和普通的参考书别无二致。
双叶拿回了她的算法书,找着梓川刚刚在看的部分。
“给出一个大于等于2的正整数n,对于一对数a和b(2<=|a|,|b|<=n,a!=b),如果存在一个整数x(|x|>=1)使得ax=b(或bx=a),就可以将a转换成b(或将b转换为a),转换后,你可以获得|x|的积分。”
一边说着,双叶就开始在黑板上写一些算式。
“不过,限制条件是,转换完毕后,就不能再使用由a转换成b或b转换成a的转换方式了。“
”一开始拥有的积分是0,现在给一个大于等于2的正数n,可以在2~n都取一次起点进行转换(更换起点时,转换方式不初始化)。请问最多可以获得多少分?”
“双叶老师,我实在是听不懂。”
梓川咲太很爽快的袒露了事实。
“
比如说n等于4的时候答案是11,因为
取起点为2时,你的最多得分是9。其中的一种得分方式是 2→(-2)→4→2→(-4)→(-2);
取起点为3时,你只能得1分,3→(-3);
取起点为4时,你别的转换方式都使用过,因此只能得1分,4→(-4)。
所以最终答案是9+1+1=11,明白了吗?
”
黑板上已经密密麻麻写了一堆公式,在右下角又写了一个Accepted。看来双叶理央已经在脑内解决了这个问题。
不过对于咲太来说这依旧是一个难题。虽然不是应考的范围,但既然看了这么久,也就顺便解答出来吧。
Input
多组输入输出。
对于每一组数据,输入一个整数n(2<=n<=100000)
保证n的个数小于200,n的总和不超过5000000
Output
对于每一组样例
输出梓川咲太最大能够得到的分数
Sample Input
2
4
6
Sample Output
1
11
33
C++版本一
预处理一下
/*
*@Author: STZG
*@Language: C++
*/
#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<deque>
#include<stack>
#include<cmath>
#include<list>
#include<map>
#include<set>
//#define DEBUG
using namespace std;
typedef long long ll;
const int N=100000+10;
const double PI = acos(-1.0);
const double EXP = 1E-8;
const int INF = 0x3f3f3f3f;
int t,n,m;
ll dp[N];
bool prime(int x){
if(n==1) return 0;
if(n==2) return 1;
for(int i=2;i<=(int)sqrt(x);i++)
if(x%i==0) return 0;
return 1;
}
ll sloved(int x){
ll ans=0;
for(int i=2;i<=(int)sqrt(x);i++){
if(x%i==0){
ans+=i;
if(x/i!=i)
ans+=(x/i);
}
}
return ans;
}
int main()
{
#ifdef DEBUG
freopen("input.in", "r", stdin);
//freopen("output.out", "w", stdout);
#endif
for(int i=2;i<=N;i++){
if(prime(i))
dp[i]=dp[i-1];
else{
dp[i]=dp[i-1]+sloved(i);
}
}
while(~scanf("%d",&n)){
cout <<dp[n]*4+n-1 << endl;
}
//cout << "Hello world!" << endl;
return 0;
}
C++版本二
https://www.cnblogs.com/MingSD/p/10050324.html
题解:我们可以从样例分析中发现,我们可以经过4次跳跃之后返回到原来的这个地方。
也就是说,我们每次走到一个新的位置之后,我们可以遍历他的所有因子,再返回到这个位置,然后继续按原来的路径行事。
我们不用管他怎么走,只需要明白每出现一个数会对答案产生什么影响就好了。
最后 是 x -> -x 。
#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL mod = (int)1e9+7;
const int N = 1e5 + 100;
int vis[N];
void init(){
for(int i = 2; i < N; ++i){
for(int j = i+i, t = 2; j < N; j+=i, t++){
vis[j] += t;
}
}
}
int main(){
init();
int n;
while(~scanf("%d", &n)){
LL sum = 0;
for(int i = 2; i <= n; ++i){
sum += vis[i];
}
printf("%lld\n", sum*4+n-1);
}
return 0;
}