找数字个数。(暴力水题)

本文介绍了一种通过暴力循环解决特定数学问题的算法实现。利用C语言中的数组和循环结构,实现了判断数字是否符合特定条件的功能,并统计了指定范围内符合条件的数字数量。

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


  这道题是之前寒假时候做的一道题。当时没做出来。现在学习了大神的思路之后,自己又试着写了写。

  题目大意很好理解,主要就是怎么用最好最简单的方法来实现暴力循环。

#include<stdio.h>
#include<string.h>
int main()
{
    int n,a,b,c,d,e,f,s[11],g,sum,i;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d %d",&a,&b);
        sum=0;
        memset(s,0,sizeof(s));  //做题少,这个函数用的不多,它是将数组的所有值清零。包含在string.h的头文件中;
        c=a;
        d=b;
        while(a)              //非零为真,进行循环。
        {                         // 这里将a%10这样写,是一个很好的技巧,放在循环里,可以将a的每一位数都变为数组s的下标。

            s[a%10]=1;       并将其数组值标记为1;也就是lulu讨厌的数变为数组下标(可以理解为讨厌的下标),将数组的值记为1;

            a/=10;
        }
        while(b)             //这个循环同上;
        {
            s[b%10]=1;
            b/=10;
        }
        for(i=1;i<=1000;i++)    //开始暴力循环求解;
        {

            e=i;f=0;                     //将每次循环i的值赋给e,记f=0; 

            while(e)
            {
                if(s[e%10]==1)    //看e的每一位数是否为lulu讨厌的下标;
                {
                    f=1;                  //如果有,将f的值记为1;结束while循环;
                    break;
                }
                e/=10;              
            }
            if(f==0&&i%c!=0&&i%d!=0)     //如果经过上面的while循环后,f还为0,也就是没有找到lu讨厌的下标,且i不为c,d倍数。则该数为lu喜欢的数。
                sum++;
        }
        printf("%d\n",sum);
    }
    return 0;
}
<think>我们正在讨论猜数字游戏的算法实现和逻辑分析。根据用户提供的引用,猜数字游戏有多种变体,但核心逻辑通常包括:1.生成一个秘密数字(通常是随机生成的,长度固定,如4位数)2.玩家输入猜测的数字3.系统比较猜测数字和秘密数字,给出提示:通常包括位置和数字都正确的个数(A)和数字正确但位置不对的个数(B)4.重复步骤2和3直到玩家猜中或达到最大次数根据引用[1]和[2],我们主要关注的是经典猜数字游戏(如Mastermind)的提示生成算法,即如何计算A和B。算法步骤:1.首先,遍历两个字符串(秘密数字和猜测数字),统计位置和数字都相同的个数(A)。同时,为了避免重复计数,我们可以将已经匹配的位置标记或跳过。2.然后,统计数字正确但位置不对的个数(B)。这里需要注意的是,同一个数字如果在秘密数字中出现多次,那么在猜测数字中出现的次数不能超过秘密数字中出现的次数。具体实现:我们可以使用两个数组(或哈希表)分别统计秘密数字和猜测数字中每个数字出现的次数(不包括已经匹配的位置)。然后,对于每个数字0-9(假设数字范围是0-9),取秘密数字中该数字出现的次数和猜测数字中该数字出现的次数的较小值,这个值就是该数字在两个序列中都出现的总次数(包括位置正确和位置不正确的)。因此,数字正确(包括位置正确)的总次数= min(秘密数字数字i的出现次数,猜测数字数字i的出现次数)对所有i求和。那么,数字正确但位置不对的个数(B)=总次数 -A(位置正确的个数)。注意:在引用[4]中,这个游戏被称为Bulls andCows,其中Bulls就是A,Cows就是B。下面我们用一个例子来说明:秘密数字:1122猜测数字:1234第一步:计算A(位置和数字都正确)第0位:1和1 ->正确,A=1第1位:1和2 ->不同第2位:2和3 ->不同第3位:2和4 ->不同所以A=1第二步:统计每个数字的出现次数(跳过已经匹配的位置?但注意,我们统计的是整个序列中每个数字出现的次数,但需要排除位置正确的数字吗?实际上,在计算总共同出现的数字时,我们不需要排除位置正确的,因为位置正确的也是共同出现的。但是,在计算B时,我们需要减去A,因为B要求位置不正确。秘密数字:1出现2次,2出现2次猜测数字:1出现1次,2出现1次,3出现1次,4出现1次对于数字1:min(2,1)=1对于数字2:min(2,1)=1对于数字3:min(0,1)=0对于数字4:min(0,1)=0总共同出现的数字次数=1+1 =2因此,B =总共同出现次数 -A =2-1 =1但是,在引用[1]中的例子:猜1234,计算机告诉玩家猜对了2个数字,其中一个在正确的位置。这里猜对了2个数字(即总共同出现2次),其中1个位置正确(A=1),另一个位置不正确(B=1)。所以我们的计算符合。再看另一个例子:猜测1111,秘密1122A:第0位1相同,第1位1相同(秘密第1位是1,猜测第1位是1),所以A=2?但是秘密数字第0位和第1位都是1,而猜测数字前两位都是1,所以:第0位:1==1-> A=1第1位:1==1 ->A=2第2位:2!=1->不匹配第3位:2!=1->不匹配所以A=2然后统计共同出现数字:秘密数字:1出现2次,2出现2次猜测数字:1出现4次对于1:min(2,4)=2对于2:min(2,0)=0总共同出现次数=2因此B=总共同出现次数-A=2-2=0所以提示为:猜对2个数字,有2个在正确的位置。符合引用[1]描述。因此,算法可以总结为:1.初始化A=02.遍历每个位置i,如果secret[i]==guess[i],则A++,并记录这个位置已经被匹配(或者我们可以不记录,因为后面统计次数时,位置正确的已经被计算在内,而B需要排除位置正确的,所以我们在统计总共同出现时包括了位置正确的,然后减去A即可)3.使用两个计数器数组,分别统计secret和guess中每个数字出现的次数(注意:这里统计整个字符串,包括位置正确的部分)4.计算每个数字在secret和guess中出现次数的较小值,将这些值累加得到total5. B= total- A注意:在统计数字出现次数时,我们不需要区分位置,所以步骤3和4可以合并。代码实现(以字符串形式输入秘密数字和猜测数字,假设长度相同):伪代码:A=0count_secret=长度为10的数组(初始0)#假设数字0-9count_guess=长度为10的数组(初始0)fori inrange(len(secret)):if secret[i]== guess[i]:A+=1#注意:这里我们分别统计每个数字的出现次数,不管位置count_secret[secret[i]- '0']+=1#如果是字符,则减去'0'得到数字值count_guess[guess[i] -'0'] +=1total =0for digitin range(10):total +=min(count_secret[digit], count_guess[digit])B =total -A然后提示:A个数字位置正确,B个数字存在但位置不正确。另外,根据引用[3],还有一种猜数字游戏是猜一个100以内的正整数,然后根据猜测次数给出不同提示。这种游戏不需要计算A和B,而是比较大小。但用户的问主要集中在引用[1][2][4]所描述的类型。因此,我们将重点实现这种提示算法(Bulls andCows)。下面给出一个完整的Java实现示例(类似LeetCode299):注意:LeetCode299中,秘密数字和猜测数字都是字符串,且只包含数字,长度相同。代码实现:```javapublic StringgetHint(String secret, Stringguess){int bulls=0;intcows =0;int[]countSecret= newint[10];int[] countGuess =new int[10];for (int i=0;i <secret.length(); i++) {chars =secret.charAt(i);charg =guess.charAt(i);if(s== g) {bulls++;}countSecret[s -'0']++;countGuess[g -'0']++;}inttotal =0;for (int i=0;i <10; i++) {total+= Math.min(countSecret[i], countGuess[i]);}cows =total -bulls;returnbulls +"A" +cows +"B"; }```但是,注意:上面的代码在统计数字出现次数时,对于同一个位置,我们既在计数数组secret中加了1,也在guess中加了1。然后计算总共同出现次数(包括位置正确的)。然后减去位置正确的个数,得到位置不正确的个数。这是正确的。然而,有一个潜在的问:在位置正确的情况下,我们在两个计数数组中都加了1,这不会影响结果吗?不会,因为位置正确的情况也是共同出现的数字,所以应该被计算在总共同出现次数中。然后我们减去位置正确的个数,剩下的就是位置不正确的个数。因此,这个算法是合理的。另外,引用[2]中要求处理多组数据,直到n=0。我们可以使用上述函数来计算每一组数据中的每个猜测的提示。逻辑分析总结:1.生成秘密数字(随机生成,且不重复?根据游戏规则,有些游戏允许重复,有些不允许。在引用[1]中,秘密数字是1122,说明允许重复。所以我们的算法也要支持重复数字)2.对于每个猜测,计算bulls(A)和cows(B)并输出提示。3.直到玩家猜中(bulls等于数字长度)或者达到最大猜测次数。关于生成秘密数字:如果允许重复,则直接随机生成即可。如果不允许重复,则需要生成不重复的数字序列。根据具体游戏规则而定。用户问:猜数字游戏的算法实现或逻辑分析我们已经给出了核心算法(提示生成)的实现和逻辑分析。下面,我们生成相关问:§§相关问§§1.猜数字游戏中如何处理重复数字的情况? 2.如何生成一个不重复的4位随机数字作为秘密数字?3.猜数字游戏的时间复杂度如何分析?4.猜数字游戏有哪些优化策略(如缩小猜测范围)?</think>### 猜数字游戏算法实现与逻辑分析 猜数字游戏的核心算法在于**比较秘密数字和玩家猜测**,生成包含两个关键指标的提示: 1. **位置和数字都正确**(Bulls/A) 2. **数字正确但位置错误**(Cows/B) #### 核心算法实现(Java示例) ```java public String getHint(String secret, String guess) { int bulls = 0; int cows = 0; int[] secretCount = new int[10]; // 数字0-9的计数数组 int[] guessCount = new int[10]; // 数字0-9的计数数组 // 第一轮遍历:统计公牛数 for (int i = 0; i < secret.length(); i++) { char s = secret.charAt(i); char g = guess.charAt(i); if (s == g) { bulls++; // 位置和数字均匹配 } else { // 记录未匹配位置的数字出现次数 secretCount[s - '0']++; guessCount[g - '0']++; } } // 统计奶牛数(数字正确但位置错误) for (int i = 0; i < 10; i++) { cows += Math.min(secretCount[i], guessCount[i]); } return bulls + "A" + cows + "B"; } ``` #### 逻辑分析 1. **公牛(Bulls)计算** - 遍历秘密数字和猜测数字的每一位 - 当相同位置上的数字相等时,公牛计数增加 $$ \text{bulls} = \sum_{i=0}^{n-1} [\text{secret}[i] == \text{guess}[i]] $$ - 时间复杂度:$O(n)$,其中$n$为数字长度 2. **奶牛(Cows)计算** - 关键原则:**数字在秘密数字中出现次数的最小值**(排除公牛位置) - 创建两个长度为10的计数数组(对应数字0-9) - 统计未匹配位置中每个数字的出现次数 - 奶牛数 = 所有数字的$\min(\text{secretCount}[d], \text{guessCount}[d])$之和 $$ \text{cows} = \sum_{d=0}^{9} \min(\text{secretCount}_d, \text{guessCount}_d) $$ - 时间复杂度:$O(1)$(固定10次循环) 3. **处理重复数字** - 示例:秘密数字"1122",猜测"1222" - Bulls: 位置0的'1'匹配 → 1A - Cows: - 秘密未匹配数字计数: [1:1, 2:2] → 实际[1,2,2] - 猜测未匹配数字计数: [2:3] → 实际[2,2,2] - min(1,0)+min(2,3)=2 → 2B - 最终提示:1A2B #### 游戏流程控制 ```python # 简化版游戏流程(Python伪代码) import random def start_game(n=4, max_attempts=10): secret = ''.join(str(random.randint(0,9)) for _ in range(n)) for attempt in range(max_attempts): guess = input(f"Attempt {attempt+1}: ") hint = get_hint(secret, guess) # 调用上述提示算法 if hint == f"{n}A0B": print("You win!") return print(f"Hint: {hint}") print(f"Game Over! Secret: {secret}") ``` #### 关键特性 1. **数字重复处理** 通过计数数组自动处理重复数字(如1122),无需特殊逻辑[^1][^4]。 2. **效率优化** - 双计数数组法避免$O(n^2)$暴力比较 - 空间复杂度$O(1)$(固定长度计数数组) 3. **扩展性** 调整数字长度(如6位密码)只需修改$n$值,核心算法不变[^2]。 #### 应用场景 1. 算法教学(数组操作/计数统计) 2. 人机交互基础框架 3. 密码强度检测的简化模型 4. 数据匹配算法原型(如生物特征识别)[^4] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值