UVa 1363 (数论 数列求和) Joseph's Problem

题意:

给出n, k,求

分析:

假设,则k mod (i+1) = k - (i+1)*p = k - i*p - p = k mod i - p

则对于某个区间,i∈[l, r],k/i的整数部分p相同,则其余数成等差数列,公差为-p

然后我想到了做莫比乌斯反演时候有个分块加速,在区间[i, n / (n / i)],n/i的整数部分相同,于是有了这份代码。

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 typedef long long LL;
 5
 6 int main()
 7 {
 8     LL n, k;
 9     while(scanf("%lld%lld", &n, &k) == 2)
10     {
11         LL ans = 0;
12         LL i, j, r = min(n, k);
13         for(i = 1; i <= r; i = j + 1)
14         {
15             j = k / (k / i);
16             if(j > r) j = r;
17
18             LL d = -k / i;
19             LL l = j - i + 1;
20             LL a1 = k % i;
21             ans += (LL) (a1*l + l*(l-1)/2*d);
22         }
23         if(n > k)
24             ans += (LL) (n-k) * k;
25
26         printf("%lld\n", ans);
27     }
28
29     return 0;
30 }

代码君

后来试了一下lrj的代码,比我的短还比我的快,给跪了

 1 // UVa1363 Joseph‘s Problem
 2 // Rujia Liu
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6
 7 // 首项为a,公差为-d,除了首项之外还有n项
 8 // 末项为a-n*d,平均数为(2*a-n*d)/2
 9 long long sum(int a, int d, int n) {
10   return (long long)(2*a-n*d)*(n+1)/2;
11 }
12
13 int main() {
14   int n, k;
15   while(cin >> n >> k) {
16     int i = 1;
17     long long ans = 0;
18     while(i <= n) {
19       int q = k % i, p = k / i;
20       int cnt = n - i; // 最多还有n - i项
21       if(p > 0) cnt = min(cnt, q / p);
22       ans += sum(q, p, cnt);
23       i += cnt + 1;
24     }
25     cout << ans << "\n";
26   }
27   return 0;
28 }

更快的代码君

UVa 1363 (数论 数列求和) Joseph's Problem

时间: 2024-10-08 10:04:32

UVa 1363 (数论 数列求和) Joseph's Problem的相关文章

UVA 1363 - Joseph&#39;s Problem(数论)

UVA 1363 - Joseph's Problem 题目链接 题意:给定n, k,求出∑ni=1(k mod i) 思路:由于n和k都很大,直接暴力是行不通的,然后在纸上画了一些情况,就发现其实对于k/i相同的那些项是形成等差数列的,于是就可以把整个序列进行拆分成[k,k/2],[k/2, k/3], [k/3,k/4]...k[k/a, k/b]这样的等差数列,利用大步小步算法思想,这里a枚举到sqrt(k)就可以了,这样就还剩下[1,k/a]的序列需要去枚举,总时间复杂度为O(sqrt(

UVA 1363 Joseph&#39;s Problem

https://vjudge.net/problem/UVA-1363 n 题意:求 Σ  k%i i=1 除法分块 如果 k/i==k/(i+1)=p 那么 k%(i+1)=k-(i+1)*p= k-i*p-p = k%i-p 所以 商相同时,余数为等差数列 我不知道为什么交到vjudge一直WA,网上搜的题解交上去也WA #include<cmath> #include<cstdio> using namespace std; int main() { int n,k,i,j,

UVA 1363 Joseph&#39;s Problem 找规律+推导 给定n,k;求k%[1,n]的和。

/** 题目:Joseph's Problem 链接:https://vjudge.net/problem/UVA-1363 题意:给定n,k;求k%[1,n]的和. 思路: 没想出来,看了lrj的想法才明白. 我一开始往素数筛那种类似做法想. 想k%[1,n]的结果会有很多重复的,来想办法优化. 但没走通. 果然要往深处想. 通过观察数据发现有等差数列.直接观察很难确定具体规律:此处应该想到用式子往这个方向推导试一试. lrj想法: 设:p = k/i; 则:k%i = k-i*p; 容易想到

UVa 1363 Joseph&#39;s Problem (等差数列)

题目 题目大意 输入正整数\(n\)和\(k\)(\(1 ≤ n, k ≤ 10^9\)), 计算\(\sum_{i = 1}^{n}k\ mod\ i\). 题解 被除数固定, 除数逐次加\(1\), 直观上余数也应该有规律: 对于某一个区间\(i, i + 1, i + 2, \cdots , j\), 如果\(k\)除以它们的商的整数部分都相同, 则\(k\)除以它们的余数会是一个等差数列. 这样就就可以在枚举\(i\)的时候把它所在的等差数列之和累加到答案中, 大大降低了时间复杂度. 代

UVa1363 - Joseph&#39;s Problem(数论)

在题目中有三种情况: 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 >

UVALive - 3521 Joseph&#39;s Problem (整除分块)

给定$n,k$$(1\leqslant n,k\leqslant 10^9)$,计算$\sum\limits _{i=1}^nk\: mod\:i$ 通过观察易发现$k\%i=k-\left \lfloor \frac{k}{i} \right \rfloor*i$,因此我们考虑把$\left \lfloor \frac{k}{i} \right \rfloor$的值相同的$i$分成一组直接求和,复杂度为$O(\sqrt{n})$. 整除分块原理(选自某dalao博客) 1 #include<b

李洪强漫谈iOS开发[C语言-051]-数列求和

// //  main.c //  53 - 数列求和 - 李洪强 // //  Created by vic fan on 16/10/15. //  Copyright ? 2016年 李洪强. All rights reserved. // #include <stdio.h> int main(int argc, const char * argv[]) { //1 ,3,5,7... //中间有多少项相加 //sum = 0 + 1; //sum = 1 + 3; //sum = 4

uva 10006 数论入门题

这是一个入门的数论题目 , 只需要简单的找素数和快速幂取模 题意:输入一个数 n , 如果这个数是非素数 , 问是不是 这个2~n-1区间的所有数都满足 ? 解法:由于数据量不大 , 可以直接暴力求解 解法1: 暴力求解 #include <iostream> #include <string.h> #include <stdio.h> using namespace std; long long prime[65010]; long long n; void init

【hoj】 1017 Joseph&#39;s problem II

这个是约瑟夫的另一个变型,变为总共有2*k个人,先是K个好人后是k个坏人,要求前k次都要杀坏人,即在杀掉第一个好人之前就要把所有的坏人都杀光,所以需要我们求出满足这个条件的最小的m值: 由约瑟夫的递归模型可以发现,我们因为他的递归是从最后杀的人递归到原有的人数,所以我们可以吧顺序反过来,等价于最后杀掉k个坏人,再杀好人,这样在递归的时候就是先知道起始位置(先杀的人),这样就能迭代,由有好人时是否杀的是坏人来判定这个m是否适合,如果k次后杀到了第k个坏人则说明这个m是适合的 参考:http://w