ZOJ-2313 Chinese Girls' Amusement(大数运算 + 规律)

本文解析了一款中国女孩的游戏算法,通过寻找规律实现大数运算,解决了游戏中球传递路径的问题。文章提供了完整的代码实现,包括大数除法及减法等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:https://vjudge.net/problem/ZOJ-2313
Chinese Girls’ Amusement

You must have heard that the Chinese culture is quite different from that of Europe or Russia. So some Chinese habits seem quite unusual or even weird to us.

So it is known that there is one popular game of Chinese girls. N girls stand forming a circle and throw a ball to each other. First girl holding a ball throws it to the K-th girl on her left (1 <= K <= N/2). That girl catches the ball and in turn throws it to the K-th girl on her left, and so on. So the ball is passed from one girl to another until it comes back to the first girl. If for example N = 7 and K = 3, the girls receive the ball in the following order: 1, 4, 7, 3, 6, 2, 5, 1.
To make the game even more interesting the girls want to choose K as large as possible, but they want one condition to hold: each girl must own the ball during the game.

This problem contains multiple test cases!
The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank line between input blocks.
The output format consists of N output blocks. There is a blank line between output blocks.

Input
Input file contains one integer number N (3 <= N <= 10^2000) - the number of Chinese girls taking part in the game.

Output
Output the only number - K that they should choose.

Sample Input
2

7

6

Sample Output
3

1

题目的大意就是一个游戏,女孩们围成一个圈,从第一个女孩开始,把她手上的球传给她左边的第K个人,那个人接住球以后再传给她左边的第K个人以此类推,当球回到第一个女孩的手里的时候游戏结束,最后我们需要求的是尽可能大的K的值,而且要保证每个女孩在游戏中都要碰到球过。

思路:题目看完的时候想着可以用暴力搜,但是看到数据范围的时候,瞬间就放弃了这种想法,由于这题给的数据很大,所以很容易想到要用大数,然后推了前几组数据发现可以找到规律。

规律:如果这个数是奇数的话,输出 n/2;
如果这个数是偶数的话,再判断它除以2以后能不能被2整除,如果能的话就输出 (n/2)-1;
如果不是的话就输出 (n/2)-2;

if(n%2==0) ans=n/2;
else
{
     if((n/2)%2==0) ans=(n/2)-1;
     else ans=(n/2)-2;
}

因为数据很大,要用到大数除以整型数和大数减法,可以直接套模板(还没学Java的我表示模板真的太长了)。还要注意输出的格式。

代码;

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 20010
string s;
string Except(string s,int x)     //大数除以整型数
{
    int cmp=0,ok=0;
    string ans="";
    for(int i=0;i<s.size();i++)
    {
        cmp=(cmp*10+s[i]-'0');
        if(cmp>=x)
        {
            ok=1;
            ans+=(cmp/x+'0');
            cmp%=x;
        }
        else {
            if(ok==1) ans+='0';
        }
    }
    return ans;
}

string subinfo (string s1,string s2)  
{
    int a[maxn],b[maxn];
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    int len1=s1.size(),len2=s2.size();
    int maxlen=max(len1,len2);
    for(int i=0;i<len1;i++)
        a[i]=s1[len1-i-1]-'0';
    for(int i=0;i<len2;i++)
        b[i]=s2[len2-i-1]-'0';
    for(int i=0;i<maxlen;i++)
    {
        if(a[i]-b[i]<0)
        {
            a[i]=a[i]+10-b[i];
            a[i+1]-=1;
        }
        else a[i]-=b[i];
    }
    string str="";
    int i;
    for(i=maxlen-1;i>=0;i--)
        if(a[i]!=0) break;
    for(;i>=0;i--) str+=a[i]+'0';
    return str;
}

string biginteger(string s1,string s2)    //大数减法
{
    if(s1==s2) return "0";
    int len1=s1.size(),len2=s2.size();
    if(len1>len2) return subinfo(s1,s2);
    else if(len1<len2)
        return "-"+subinfo(s2,s1);
    else
    {
        for(int i=0;i<len1;i++)
        {
            if(s1[i]-'0'>s2[i]-'0')
                return subinfo(s1,s2);
            else if(s1[i]-'0'<s2[i]-'0')
                return "-"+subinfo(s2,s1);
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        cin>>s;
        int l1=s.size();
        if((s[l1-1]-'0')%2!=0)    //用字符串的最后一位来判断是奇数还是偶数
        {
            cout<<Except(s,2)<<endl;
        }
        else
        {
            string s1=Except(s,2);
            int l2=s1.size();
            if((s1[l2-1]-'0')%2==0)
            {
               string s3=biginteger(s1,"1");
               cout<<s3<<endl;
            }
            else
            {
                string s2=biginteger(s1,"2");
                cout<<s2<<endl;
            }
        }
        if(t!=0)
            printf("\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值