LightOJ 1245

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1245

 

题意:仿照上面那题他想求这么个公式的数。但是递归太慢啦。让你找公式咯。

题解:显然直接longlong存不下。暴力肯定不行啦。这题真的写了很久,死都不懂怎么找的公式啊。然后在wjd的帮助下懂了这题。

我们先列举几个例子

有没有发现他们的共同点,就是除到一定程度,就会变成1。这个临界点是sqrt(n)。那在sqrt(n)前面我们要算的就是这个数对于1,2,3……sqrt(n)的因子个数。

这个因子个数设为x。

n = i * x;

这个时候如果直接求是会TLE的。所以会推出来一个公式。

x  =  (n / i  - n / (i+1) ) * i;

至于这个公式怎么出来的。网上有篇博客是画图推的。QWQ。

这个公式是求什么的呢?其实就是求 x为 1~sqrt(n) 的时候,会有几个这样的式子。

拿10举例,

x = 1 ,i  = 6,7,8,9,10。 5个

x = 2 ,i  =  4 , 5。 2个

x = 3 ,i  =  3。     1个

i在1~sqrt(n)之间当然就可以直接求个数啦。 大胆的n/i。

把所有的x加起来就是答案。因为n可能为平方数,sqrt(n)可能多算了一次所以要减去这一次。

这个真的很难懂啊。QAQ、要多看几遍才行。

 1 #include<iostream>
 2 #include<cmath>
 3 #include<cstdio> 
 4 #define ll long long
 5 using namespace std;
 6 int main(){
 7     int T;
 8     cin>>T;
 9     int t = 1;
10     while(T--){
11         int n;
12         cin>>n;
13         ll sum = 0;
14         int tot = sqrt(n);
15         for(int i = 1; i <= tot ;i++){
16             sum += n / i;
17         }    //枚举 sqrt(n) ~ n  x在1~sqrt(n)直接算 
18         for(int i = 1; i <= tot ;i++ ){
19             sum += (n / i - n / (i+1)) * i;
20         }    //枚举1~sqrt(n);     x在后面就用公式 
21         if( tot  == n / tot )
22             sum -= tot;
23         printf("Case %d: %lld
",t,sum);
24         t++;
25     }    
26     return 0;
27 }
View Code
原文地址:https://www.cnblogs.com/Asumi/p/9011325.html