POJ 2800 Joseph's Problem

给n 和 k 求: ∑1<=i<=n(k
mod i).

p  = k/i

k mod i = k - p * i

k mod ( i + 1 ) = k - p * ( i + 1 ) = k mod i - p

k mod ( i + 2 ) = k - p * ( i + 2 ) = k mod i - 2 * p

对于连续的 i ,很多p都是一样的 . 相差的部分是一个等差数列 ,

i 的 范围是 从 i 到 min(k/p,n) 如果 p == 0 则 一直延续到最后


Joseph‘s Problem

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 7282   Accepted: 1891

Description

Joseph likes taking part in programming contests. His favorite problem is, of course, Joseph‘s problem.

It is stated as follows.

    There are n persons numbered from 0 to n - 1 standing in a circle. The person numberk, counting from the person number 0, is executed. After that the person number k of the remaining persons is executed, counting from the person after the last executed one.
    The process continues until only one person is left. This person is a survivor. The problem is, given n and k detect the survivor‘s number in the original circle.

Of course, all of you know the way to solve this problem. The solution is very short, all you need is one cycle:

	r := 0;

	for i from 1 to n do

		r := (r + k) mod i;

	return r;

Here "x mod y" is the remainder of the division of x by y, But Joseph is not very smart. He learned the algorithm, but did not learn the reasoning behind it. Thus he has forgotten the details of the algorithm and remembers the solution just approximately.

He told his friend Andrew about the problem, but claimed that the solution can be found using the following algorithm:

	r := 0;

	for i from 1 to n do

		r := r + (k mod i);

	return r;

Of course, Andrew pointed out that Joseph was wrong. But calculating the function Joseph described is also very interesting.

Given n and k, find ∑1<=i<=n(k mod i).

Input

The input file contains n and k (1<= n, k <= 109).

Output

Output the sum requested.

Sample Input

5 3

Sample Output

7

Source

Northeastern Europe 2005

[Submit]   [Go Back]   [Status]  
[Discuss]

/* ***********************************************
Author        :CKboss
Created Time  :2015年02月02日 星期一 10时53分55秒
File Name     :POJ2800.cpp
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;

typedef long long int LL;

LL n,k;

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);

	while(cin>>n>>k)
	{
		LL ret=0;
		for(int i=1;i<=n;i++)
		{
			LL p = k/i;
			if(p==0)
			{
				ret += (n-i+1)*k;
				break;
			}
			else
			{
				LL q = k/p;
				if(q>n) q = n;
				LL md = k%i;
				LL num = q-i+1;
				LL temp = md*num-(num-1)*num/2*p;
				ret += temp;
				i=q;
			}
		}
		cout<<ret<<endl;
	}

    return 0;
}

POJ 2800 Joseph's Problem

时间: 2024-10-03 13:13:38

POJ 2800 Joseph's Problem的相关文章

POJ 2800 Joseph’s Problem 数论找规律

Description 求 Input 两个整数n和k(1<=n,k<=1e9) Output 输出 Sample Input 5 3 Sample Output 7 暴力超时,这样就打下表找下余数的规律.输入100,27,一下子就可以看出来,倒着的看,是一段一段的等差序列. 例如100 25 除数 1    2    3    4    5    6    7    8    9     10     11    12   13 14  15  ......25   26........ 商

POJ 3468 A Simple Problem with Integers(线段树)

题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 56005   Accepted: 16903 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with

poj 3468 A Simple Problem with Integers 【线段树-成段更新】

题目:poj 3468 A Simple Problem with Integers 题意:给出n个数,两种操作 1:l -- r 上的所有值加一个值val 2:求l---r 区间上的和 分析:线段树成段更新,成段求和 树中的每个点设两个变量sum 和 num ,分别保存区间 l--r 的和 和l---r 每个值要加的值 对于更新操作:对于要更新到的区间上面的区间,直接进行操作 加上 (r - l +1)* val .下面的区间标记num += val 对于求和操作,每次进行延迟更新,把num值

POJ 3468 A Simple Problem with Integers(线段树区间更新)

题目地址:POJ 3468 打了个篮球回来果然神经有点冲动..无脑的狂交了8次WA..居然是更新的时候把r-l写成了l-r... 这题就是区间更新裸题.区间更新就是加一个lazy标记,延迟标记,只有向下查询的时候才将lazy标记向下更新.其他的均按线段树的来就行. 代码如下: #include <iostream> #include <cstdio> #include <cstring> #include <math.h> #include <stac

poj 3466 A Simple Problem with Integers

题目链接:http://poj.org/problem?id=3468 http://poj.org/problem?id=3468 http://poj.org/problem?id=3468 思路:这是一个区间修改区间查询的题,由于题目中的给的数据比较大,那么用单个修改和查询肯定不行,所以....注意数据可能比较大,应该用__int64或long long存数据..... code: #include<stdio.h> #include<math.h> #define L(u)

POJ 1012 Joseph

Joseph Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 53862   Accepted: 20551 Description The Joseph's problem is notoriously known. For those who are not familiar with the original problem: from among n people, numbered 1, 2, . . ., n,

POJ 3468 A Simple Problem with Integers 【树状数组】

题目链接:http://poj.org/problem?id=3468 题目大意:给出一组数组v[i],有两种操作,一种给出两个数a,b,要求输出v[a]到v[b]之间的和,另一种给出三个数a,b,c,让v[a]到v[b]之间的数全都加上c. 完全是树状数组能够实现的功能,但是如果就这样单纯的套用模板,做第二种操作是更新每个值,这样的操作就有可能超时. 换一种思路,既然第二种操作是给某区间上的所有数加上相同的值,那么应该是能够简化的才对. 假设数组sum[i]为原数组从v[1]到v[i]的和,数

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,

poj 3590 The shuffle Problem(置换群+DP)

题目链接:poj 3590 The shuffle Problem 题意: 给你一个数n,让你找一个字典序最小的置换序列,使得变换整个周期最大. 题解: 由于置换群的性质,我们可以将n拆分成m个数,使得这m个数的和为n,并且这m个数的最小公倍数最大. dp可以求出将n拆分后的最大的最小公倍数. 然后可以将这个最大的最小公倍数分解为pi^mi+pi^mi+pi^mi.... 对于每一个pi^mi,就是一个循环的轮数. 然后将这些循环的轮数排序后输出对于的数字就行了. PS:当前面的总和sum小于n