UVALive - 3882 And Then There Was One (递推[dp])
2016-09-05 21:21
399 查看
大体题意:
给你一个由n 个数(1~n)组成的圆环,刚开始删除m,以后每数k 个数删除一个数,求最后剩下哪个数?
思路:
这个题数据量比较大,什么数组模拟,链表模拟, 都会超时!
这个题目不就是猴子选大王吗= =!
看了看相关约瑟夫问题的讲解,感觉很巧妙!简单记录一下:
有这么一类问题:
给你1~n 的圆环,你从1报数,报到m 停止删除这个数,继续报,求最后的人?
因为涉及到取余问题,可以改变一下数据,给你一个0~n-1 的圆环,你从0报数,报到m-1停止,删除这个数,继续报,求最后的人?
这两个问题是一样的!
第一次报数肯定是m%n 这个位置就退出了! 我们令 k = m % n
那么剩下的人就是:
k k+1 k+2 .... n-1 0 1 2 ... k-2
我们可以给他们重新编号:
k--->0
k+1 ---> 1
k+2 ---->2
k-2 ----->n-2
这样只剩下了n-1个人,假设我们知道这n-1个人的结果 为dp[n-1]的话,那么很容易推出 n 个人是多少了!
观察数据也可以知道 dp
= (dp[n-1] + k) % n
而dp[1] = 0 (显然),因此这个递推式就有了!
这样dp
表示的是 从0~n-1 这个n个人报数 报到k删除 继续的结果!!
然而这个题目 是 一开始就删除了m , 这就相当于 从m-k+1开始报数
也就是由原来的0 ---> m-k+1
因此我们要给dp
+= m-k+1适合这个题目!
注意取模问题!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 10000 + 10;
int dp[maxn];
int main(){
int n,k,m;
while(scanf("%d %d %d",&n, &k, &m) == 3 && (n || k || m)){
dp[1] = 0;
for (int i = 2; i <= n; ++i){
dp[i] = (dp[i-1] % i + k % i) % i;
}
dp
= (dp
%n + (m-k+1) % n) % n;
if (dp
<= 0)dp
+= n;
printf("%d\n",dp
);
}
return 0;
}
/*
8 5 3
100 9999 98
10000 10000 10000
0 0 0
*/
给你一个由n 个数(1~n)组成的圆环,刚开始删除m,以后每数k 个数删除一个数,求最后剩下哪个数?
思路:
这个题数据量比较大,什么数组模拟,链表模拟, 都会超时!
这个题目不就是猴子选大王吗= =!
看了看相关约瑟夫问题的讲解,感觉很巧妙!简单记录一下:
有这么一类问题:
给你1~n 的圆环,你从1报数,报到m 停止删除这个数,继续报,求最后的人?
因为涉及到取余问题,可以改变一下数据,给你一个0~n-1 的圆环,你从0报数,报到m-1停止,删除这个数,继续报,求最后的人?
这两个问题是一样的!
第一次报数肯定是m%n 这个位置就退出了! 我们令 k = m % n
那么剩下的人就是:
k k+1 k+2 .... n-1 0 1 2 ... k-2
我们可以给他们重新编号:
k--->0
k+1 ---> 1
k+2 ---->2
k-2 ----->n-2
这样只剩下了n-1个人,假设我们知道这n-1个人的结果 为dp[n-1]的话,那么很容易推出 n 个人是多少了!
观察数据也可以知道 dp
= (dp[n-1] + k) % n
而dp[1] = 0 (显然),因此这个递推式就有了!
这样dp
表示的是 从0~n-1 这个n个人报数 报到k删除 继续的结果!!
然而这个题目 是 一开始就删除了m , 这就相当于 从m-k+1开始报数
也就是由原来的0 ---> m-k+1
因此我们要给dp
+= m-k+1适合这个题目!
注意取模问题!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 10000 + 10;
int dp[maxn];
int main(){
int n,k,m;
while(scanf("%d %d %d",&n, &k, &m) == 3 && (n || k || m)){
dp[1] = 0;
for (int i = 2; i <= n; ++i){
dp[i] = (dp[i-1] % i + k % i) % i;
}
dp
= (dp
%n + (m-k+1) % n) % n;
if (dp
<= 0)dp
+= n;
printf("%d\n",dp
);
}
return 0;
}
/*
8 5 3
100 9999 98
10000 10000 10000
0 0 0
*/
相关文章推荐
- UVALive3882-And Then There Was One-约瑟夫问题-递推
- UVa 3882 - And Then There Was One 递推------------无力orz
- UVa 3882 - And Then There Was One 递推------------无力orz
- And Then There Was One UVALive - 3882
- UVALive 3882 And Then There Was One 约瑟夫环问题
- UVALive - 3882:And Then There Was One
- UVALive 3882 And Then There Was One
- UVALive 3882 And Then There Was One
- UVALive - 3882 And Then There Was One (约瑟夫环变形)@
- UVALive 3882 And Then There Was One 约瑟夫环问题
- ecjtu-summer training #5 F - And Then There Was One UVALive - 3882
- uva live 3882 And Then There Was One 约瑟夫环
- UVALive - 3882 And Then There Was One 约瑟夫的变形问题
- UVALive 3882 - And Then There Was One【约瑟夫问题】
- LA - 3882 - And Then There Was One(dp)
- UVA 1394 POJ 3517 And Then There Was One (双向循环链表和递推)
- UVa 3882 And Then There Was One(stl+有技巧的模拟||数学方法+约瑟夫问题)
- 【UVa】And Then There Was One(dp)
- UVA 1394 And Then There Was One / Gym 101415A And Then There Was One / UVAlive 3882 And Then There Was One / POJ 3517 And Then There Was One / Aizu 1275 And Then There Was One (动态规划,思维题)
- 约瑟夫问题变形 And Then There was One, LA 3882 递推 动态规划