zoukankan      html  css  js  c++  java
  • noip胡测之8.15(没有正解)


    T1 约瑟夫游戏
    (joseph.cpp/c/pas)
    【问题描述】
    YJC 很喜欢玩游戏,今天他决定和朋友们玩约瑟夫游戏。
    约瑟夫游戏的规则是这样的:n 个人围成一圈,从 1 号开始依次报数,当报到 m 时,报 1、2、…、m-1 的人出局,下一个人接着从 1开始报,保证(n-1)是(m-1)的倍数。最后剩的一个人获胜。
    YJC 很想赢得游戏,但他太笨了,他想让你帮他算出自己应该站在哪个位置上。
    【输入格式】
    第一行包含两个整数 n 和 m,表示人数与数出的人数。
    【输出格式】
    输出一行,包含一个整数,表示站在几号位置上能获得胜利。
    【输入输出样例】
    joseph.in
    10 10
    joseph.out
    10
    【数据说明】
    对于 30%的数据,满足 2≤n≤1000;
    对于 50%的数据,满足 2≤n≤1000000;
    对于 100%的数据,满足 2≤m≤n<263-1 且(n-1)是(m-1)的倍数。

    分析:
    先说一下我的骗分:
    打表发现,答案(几乎,大佬说有特例)等于n/m*m
    再加上30分的暴力,妥妥50

    看一下正解:
    我们来一句一句解释:
    这里写图片描述
    第一句挺简单
    now是现在有的人数,last是上次%m的余数
    当now=m时,last是一定要被踢掉的,
    now-last计算的就是,在剩下的除了余数的m的倍数中,留下的是第几个
    这里写图片描述
    第二句就是递归了
    这里写图片描述
    最后一句计算答案
    t*m计算的就是相对于上一层
    答案是第几个
    (以上一层最后一个整除位之后的那一位为第一位,说白了就是不算余数)
    因为上一层还有一定的余数,所以最后要减去last
    这里写图片描述
    看一个大一点的样例
    这里写图片描述

    这里写代码片
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define ll long long
    
    using namespace std;
    
    ll n,m;
    
    ll solve(ll now,ll last)
    {
        if (now==m) return now-last;   //剩下的人恰好是m个
        ll t=solve(now/m+now%m,now%m);
        return t*m-last; 
    }
    
    int main()
    {
        //freopen("joseph.in","r",stdin);  
        //freopen("joseph.out","w",stdout);
        scanf("%lld%lld",&n,&m);  //(n-1)%(m-1)==0
        printf("%lld",solve(n,0));
        return 0;
    }

    T2 密码游戏
    (password.cpp/c/pas)
    【问题描述】
    YJC 很喜欢玩游戏,今天他决定和朋友们玩密码游戏。
    密码游戏的规则是这样的:初始时有两个大小为 m 的数组 a 和 b,分别是 0~m-1 的一
    个排列。每一次操作在 0~m-1 之间选一个数 x,求出结果 y=b[a[x]],把 x 和 y 写下来。之
    后,a 数组向前循环移动一次,即(a[0],a[1],…,a[m-2],a[m-1])变成(a[1],a[2],…,a[m-1],a[0])。
    当 a 数组变回初始状态时,b 数组向前循环移动一次。现在知道所有的 x 和 y,如果 YJC 能
    求出任意一组符合条件的 a 和 b 的初值,YJC 就赢了。
    YJC 很想赢得游戏,但他太笨了,他想让你帮他算出 a 和 b 的初值。
    【输入格式】
    第一行包含两个整数 n 和 m,表示操作了多少次和 a、b数组的大小。
    第二行包含 n 个整数,第 i个数表示第 i次选出的 x。
    第二行包含 n 个整数,第 i个数表示第 i次求出的 y。
    【输出格式】
    第一行包含 m 个整数,表示 a的初值。
    第二行包含 m 个整数,表示 b的初值。如果有多组答案,输出任意一组即可。
    【输入输出样例】
    password.in
    4 2
    0 0 0 0
    0 1 1 0
    password.out
    0 1
    0 1
    【数据说明】
    对于 30%的数据,满足 m≤5,n≤1000。
    对于 100%的数据,满足 2≤m≤26,m2≤n≤100000,保证数据随机,且存在至少一组 a和 b。

    分析:
    考场上写30分暴力
    然而我是先暴力构造a串,之后再通过x和y构建b,只要找到一对合法就输出,这样就玄学的拿了40分

    这里写代码片  //40%
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    
    using namespace std;
    
    const int N=100010;
    int n,m;
    int x[N],y[N],a[30],b[30];
    bool p[30],ff=0;
    
    int pd()
    {
        bool pp[30];
        memset(pp,1,sizeof(pp));
        memset(b,-1,sizeof(b));
        int i,j;
        int t1=0,t2=0;
        for (i=1;i<=n;i++)
        {
            int r=a[(x[i]+t1)%m];  //t1  begin
            if (b[(r+t2)%m]==-1) b[(r+t2)%m]=y[i],pp[y[i]]=0;
            else if (b[(r+t2)%m]!=y[i]) return 0;
            t1++; t1%=m;
            if (t1==0) t2++,t2%=m;
        }
        t1=0;
        for (i=0;i<m;i++) 
            if (b[i]==-1)
            {
                while (pp[t1]==0) t1++,t1%=m;
                b[i]=t1; pp[t1]=0;
            }
        for (i=0;i<m;i++) printf("%d ",a[i]);
        puts("");
        for (i=0;i<m;i++) printf("%d ",b[i]);
        return 1;
    }
    
    void ss(int t)
    {
        if (t==m)
        {
            if (pd()) ff=1;
            return;
        }
        if (ff) return;
        for (int i=0;i<m;i++)
            if (p[i])
            {
                a[t]=i;
                p[i]=0;
                ss(t+1);
                if (ff) return;
                p[i]=1;
                a[t]=0;
            }
        if (ff) return;
    }
    
    int main()
    {
        freopen("password.in","r",stdin);  
        freopen("password.out","w",stdout);
        memset(p,1,sizeof(p));
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) scanf("%d",&x[i]);
        for (int i=1;i<=n;i++) scanf("%d",&y[i]);
        ss(0);
        return 0;
    }
  • 相关阅读:
    14.2.2.4 InnoDB Record, Gap, and Next-Key Locks
    Linux_PXE服务器_RHEL7
    Linux_PXE服务器_RHEL7
    Caused by: java.net.SocketException: Connection reset
    mysql read committed
    Linux_OpenSSH远程连接
    Linux_OpenSSH远程连接
    dns nsswitch.conf
    Python基本语法_强制数据类型转换
    Python基本语法_强制数据类型转换
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673438.html
Copyright © 2011-2022 走看看