数学题中的大智慧

来源:互联网 发布:阿里云tv助手连接电视 编辑:程序博客网 时间:2024/03/29 02:39

题3约瑟夫问题

【问题描述】

    正如经典的约瑟夫问题,N个人顺时针围成一圈,以1~N标号。

从第一个人开始按顺时针方向报数。当某人报到2时,这个人就要出局。然后从这个人顺时针数剩下的第一个人开始继续报数。这样一直到只剩下一个人为止。

比如有3个人顺时针站成一圈,记为(1, 2, 3),以下模拟报数的过程:

初始: (1, 2, 3)

2出局:(1, 3)

1出局:(3)

则最终剩下来唯一一个人为3。

记J(N)表示N个人报数剩下的那个人的标号,比如说J(3) = 3。

【输入格式】

    一个整数N,满足1 <= N <= 10^9。

【输出格式】

    一个整数J(N)。

【输入样例】

3

【输出样例】

3



看到这道题以后,是不是一脸懵逼。


其实,我也是一脸懵逼。


但是,转念一想。


找规律啊!


于是,我就委托LLN同学打了个暴力,找了找规律


打出来 一看


懆懆懆懆操操懆懆


尼玛炸了




是不是恍然大悟呢


其实,就是那么简单!!!


//head
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pr;
const double pi=acos(-1);
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define Rep(i,u) for(int i=head[u];i;i=Next[i])
#define clr(a) memset(a,0,sizeof a)
#define pb push_back
#define mp make_pair
#define fi first
#define sc second
ld eps=1e-9;     
ll pp=1000000007;
ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
ll read(){
ll ans=0;
char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans;
return ans;
}
//head


int main()
{
    int N=read();
    long long mi=1;
    while (mi <= N)
    {
        mi=mi*2;
    }
    mi=mi / 2;
    int Ans=1;
    Ans=Ans+(N - mi) * 2;
    printf("%d %d\n",N,Ans);
    while (1);
}



1 0