Joseph UVA 1452 Jump

题目传送门

 1 /*
 2     数学:约瑟夫环问题的变形,首先定义f[i]表示剩下i个人时,最后一个选出的人,有个公式:f[i] = (f[i-1] + m) % i
 3         f[1] = 0(编号从0开始),那么类似最后一个数的求法,先找到剩2个人和剩3个人时,最后的编号,然后跟着最后一个的一起递推
 4 */
 5 /************************************************
 6 * Author        :Running_Time
 7 * Created Time  :2015-8-8 14:26:38
 8 * File Name     :UVA_1459.cpp
 9  ************************************************/
10
11 #include <cstdio>
12 #include <algorithm>
13 #include <iostream>
14 #include <sstream>
15 #include <cstring>
16 #include <cmath>
17 #include <string>
18 #include <vector>
19 #include <queue>
20 #include <deque>
21 #include <stack>
22 #include <list>
23 #include <map>
24 #include <set>
25 #include <bitset>
26 #include <cstdlib>
27 #include <ctime>
28 using namespace std;
29
30 #define lson l, mid, rt << 1
31 #define rson mid + 1, r, rt << 1 | 1
32 typedef long long ll;
33 const int MAXN = 5e5 + 10;
34 const int INF = 0x3f3f3f3f;
35 const int MOD = 1e9 + 7;
36
37 void Joseph(int n, int m)    {
38     int ans1 = 0, ans2 = 0, ans3 = 0;
39     for (int i=2; i<=n; ++i)    {
40         ans1 = (ans1 + m) % i;
41         if (i == 2) {       //2个人就是0或1
42             ans2 = !ans1;
43         }
44         else if (i == 3)    {
45             ans2 = (ans2 + m) % i;
46             bool vis[3];    memset (vis, false, sizeof (vis));
47             vis[ans1] = vis[ans2] = true;
48             for (int i=0; i<3; ++i) {
49                 if (!vis[i])    {
50                     ans3 = i;   break;
51                 }
52             }
53         }
54         else    {
55             ans2 = (ans2 + m) % i;
56             ans3 = (ans3 + m) % i;
57         }
58     }
59
60     printf ("%d %d %d\n", ans3 + 1, ans2 + 1, ans1 + 1);
61 }
62
63 int main(void)    {     //UVA 1452 Jump
64     int T;  scanf ("%d", &T);
65     while (T--) {
66         int n, m;   scanf ("%d%d", &n, &m);
67         Joseph (n, m);
68     }
69
70     return 0;
71 }
时间: 2024-10-29 17:52:51

Joseph UVA 1452 Jump的相关文章

UVA 1452 八 Jump

Jump Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UVA 1452 Integers 1, 2, 3,..., n are placed on a circle in the increasing order as in the following figure. We want to construct a sequence from these

【UVa】Jump(dp)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4198 约瑟夫变形 根据f(n)=(f(n-1)+m)%n 因为是求倒数第几个 那么我们只要求出f(倒数第几个)的值然后再带进去即可. (没理解的自行面壁..) 而f(倒数第几个)=(m-1)%倒数第几个 然后就行了.. #include <cstdio> #include <

uva 1452(约瑟夫变形)

题意:有1到n顺时针坐在圆桌上,编号从1到n,从1开始顺时针报数,每k个出去一个人,输出倒数第三个出去.倒数第二个出去.倒数第一个出去的人的编号. 题解:n的范围是500000,肯定不能用链表来解,这就用到了约瑟夫问题的递推式:f[i] = (f[i - 1] + k) % i,初始f[1] = 0表示还剩1个人的时候最后出去的人编号一定是0(这里默认编号从0开始),那么根据递推式可以得到f[n]就是还剩n个人最后出去的人,倒数第二个人也可以通过这个式子推导出来:(k + 1) % 2是还剩两个

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(数论)

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

题意: 给出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

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\)的时候把它所在的等差数列之和累加到答案中, 大大降低了时间复杂度. 代

uva 11557 - Code Theft(KMP)

题目链接:uva 11557 - Code Theft 题目大意:给定n个文本,每个文本有一个文本名,现在给出一个文本,求给定文本和n个文本中连续相同行数最大值,并且输出文本名,注意为0时不用输出其它的文本名. 解题思路:将每个字符串用映射成一个hash值,然后对匹配文本枚举后缀,建立失配数组进行KMP匹配,记录下每个文本的匹配最大值. #include <cstdio> #include <cstring> #include <map> #include <st