UVa1363 - Joseph's Problem(数论)
2015-05-10 22:07
357 查看
在题目中有三种情况:
1、1<k<n;
2、k == n ;
3、k>n;
对于第一种情况我们可以分为1到k和k到n两个子问题来解。
1.1、1到k:
for( i = 1 , sum = 0 ; i <= k ; i ++ ) sum += k %i ;
1.2、k到n: sum =(n-k)*k;
而对于第二种情况就是第一种情况的(1)。但是就这样写的话时明显的tle的。
对于第二种情况也可以分为几个小问题来求解:
2.1、1到k/2:
for( i = k/2 ; i >=1 ; i-- ) sum+= k % i ;
2.2、k/2到k:
k%k+((k-1)+1)%(k-1)+.......+ (k-m0)+m0)%(k-m0) 其中m0 < k –m0 , 则m0<k/2, 又因为m0 是整数所以m0
= k/2 – 1 ;
简单的来说:如果k%i ( i ++ ) 只要 k/i (i ++ ) 的值相同 , 则 k % i 是以个等差数列 例如:
k = 100 , i = 26
100 % 26 = 22 100 / 26 = 3
100 % 27 = 19 100 / 27 = 3
100 % 28 = 16 100 / 28 = 3
100 % 29 = 13 100 / 29 = 3
所以 sum = sum(2.1) + sum(2.2) ;
然而2.1在k=10^9时所需的时间也是很大的,所以继续优化:
同理可得到for( i=k/2;i>=1;i-- ) 也可以化简成:
2.1.1、( (k/2)*2+m1 )%(k/2)+((k/2-1)*2+m1+2)%(k/2-1)+...+((k/2-x)*2+m1+2*x)%(k/2-x);
这里的m1=k%(k/2),因为在2.2式子中的m0=k/2-1 , 则 m1 = k%(k/2) ,且x=k/6-1;
2.1.1的式子是公差为2的等差数列;
2.1.2、for(i=k/3;i>=1;i--)
sum+=k%i;
综上可以知道,对于原来的线性搜索便可以拆成若干个等差数列的和。由此可以将式子化简成:
(k%(k/1)+k%(k/2+1))*(k/1-k/2)/2+(k%(k/2)+k%(k/3+1))*(k/2-k/3)/2+…设s=k/i;e=k/(i-1);
则上诉式子就变为: sum+=(k%e+k%(s+1))*(e-s)/2; 而它的时间复杂度仅为sqrt(k);
对于第三种情况,既k>n的情况,是第二种情况的特殊情况,区别就是把首相变成k%n而已。
3.1、1<n<sqrt(k);
3.2、1<sqrt(k)<n;
所以综合上面的可以知道,我们可以把sum分为三部分:
1、 sum+=(k%e+k%(s+1))*(e-s)/2
2、for(i=1;i<=n&&i<=b;i++) sum+=k%i; 其中b = k / sqrt(k) ;
3、 sum += (n-k)
1、1<k<n;
2、k == n ;
3、k>n;
对于第一种情况我们可以分为1到k和k到n两个子问题来解。
1.1、1到k:
for( i = 1 , sum = 0 ; i <= k ; i ++ ) sum += k %i ;
1.2、k到n: sum =(n-k)*k;
而对于第二种情况就是第一种情况的(1)。但是就这样写的话时明显的tle的。
对于第二种情况也可以分为几个小问题来求解:
2.1、1到k/2:
for( i = k/2 ; i >=1 ; i-- ) sum+= k % i ;
2.2、k/2到k:
k%k+((k-1)+1)%(k-1)+.......+ (k-m0)+m0)%(k-m0) 其中m0 < k –m0 , 则m0<k/2, 又因为m0 是整数所以m0
= k/2 – 1 ;
简单的来说:如果k%i ( i ++ ) 只要 k/i (i ++ ) 的值相同 , 则 k % i 是以个等差数列 例如:
k = 100 , i = 26
100 % 26 = 22 100 / 26 = 3
100 % 27 = 19 100 / 27 = 3
100 % 28 = 16 100 / 28 = 3
100 % 29 = 13 100 / 29 = 3
所以 sum = sum(2.1) + sum(2.2) ;
然而2.1在k=10^9时所需的时间也是很大的,所以继续优化:
同理可得到for( i=k/2;i>=1;i-- ) 也可以化简成:
2.1.1、( (k/2)*2+m1 )%(k/2)+((k/2-1)*2+m1+2)%(k/2-1)+...+((k/2-x)*2+m1+2*x)%(k/2-x);
这里的m1=k%(k/2),因为在2.2式子中的m0=k/2-1 , 则 m1 = k%(k/2) ,且x=k/6-1;
2.1.1的式子是公差为2的等差数列;
2.1.2、for(i=k/3;i>=1;i--)
sum+=k%i;
综上可以知道,对于原来的线性搜索便可以拆成若干个等差数列的和。由此可以将式子化简成:
(k%(k/1)+k%(k/2+1))*(k/1-k/2)/2+(k%(k/2)+k%(k/3+1))*(k/2-k/3)/2+…设s=k/i;e=k/(i-1);
则上诉式子就变为: sum+=(k%e+k%(s+1))*(e-s)/2; 而它的时间复杂度仅为sqrt(k);
对于第三种情况,既k>n的情况,是第二种情况的特殊情况,区别就是把首相变成k%n而已。
3.1、1<n<sqrt(k);
3.2、1<sqrt(k)<n;
所以综合上面的可以知道,我们可以把sum分为三部分:
1、 sum+=(k%e+k%(s+1))*(e-s)/2
2、for(i=1;i<=n&&i<=b;i++) sum+=k%i; 其中b = k / sqrt(k) ;
3、 sum += (n-k)
<pre name="code" class="cpp">#include<stdio.h> #include<string.h> #include<math.h> long long n,k; long long solve(){ long long ans=0; if(n>k) ans+=(n-k)*k; long long a=(long long)sqrt(k),b=k/a; for(long long i=a;i>1;i--){ long long a0=k/i,an=k/(i-1); if(a0>n) break; if(an>n) an=n; ans+=(k%an+k%(a0+1))*(an-a0)/2; } for(int i=1;i<=n&&i<=b;i++) ans+=k%i; return ans; } int main(){ while(~scanf("%lld%lld",&n,&k)){ printf("%lld\n",solve()); } }
相关文章推荐
- UVA - 1363 Joseph's Problem
- uva 1363 - Joseph's Problem(数论)
- POJ 2800 Joseph's Problem(数论)
- UVA 1363 - Joseph's Problem(数论)
- UVA 1363 Joseph's Problem(数论)
- uva 10239 The Book-shelver's Problem (dp)
- UVa 1363 Joseph's Problem
- UVA 1363(p338)----Joseph's Problem
- 1085.Longge's problem (数论,欧拉积性函数)
- UVa 1363 POJ 2800 Joseph's Problem
- uva 10026 Shoemaker's Problem (贪心)
- UVa 1363 (数论 数列求和) Joseph's Problem
- UVA 10831 - Gerg's Cake(数论)
- UVA - 1363 Joseph's Problem(打表找规律)
- UVA 10026 Shoemaker's Problem
- ZOJ 2646 Joseph's Problem
- uva 1363 Joseph's Problem 等差数列
- uva1363 Joseph's Problem
- UVA 10061 How many zero's and how many digits ?(数论)
- UVa 1363 Joseph's Problem (数论)