文章

2

粉丝

489

获赞

2

访问

22.7k

头像
求解为什么就是通过不了,答案错误,哭
P1176 清华大学上机题
发布于2019年11月27日 09:36
阅读数 12.0k

#include<stdio.h>
int p(int a[],int n)
{static int i=0;
if(n==0) {a[i]=i;return(a[i]);}
else {a[i]=n%2;
        n=n/2;
        i++;
      return(p(a,n));}
}
int o(int x,int s[])
{static int i=0,n;
 if(s[i]>1) n=0;
 else {i++;n=s[x-i]+o(x,s)*2;}
   return(n);
}
int main()
{int a[100],n,x;
scanf("%d",&n);
 x=p(a,n);
 n=o(x,a);
 printf("%d",n);
 return 0;
}
 

登录查看完整内容


登录后发布评论

3 条评论
tyu007
2020年3月8日 23:07

仔细看题。题目说是一千位,这是大数。得用字符数组。不能用int 型

赞(0)
admin SVIP
2019年11月27日 18:33

这个题的输入数据范围很大,不是int或者long long能够解决的,他是一个大数。

参考下面这个代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = 4000;  // 因为输入的10进制不超过1000位,则转换成2进制应该不超过4000位(2^4 = 16)
const int oldBase = 10; // 原始进制
const int newBase = 2;  // 新进制

string str;             // 因为输入为不超过1000位的10进制数则应该用字符串接收
/**
    数组的 0 号元素均用于存储数组的长度
*/
int br[maxn] = {0};     // 存储2进制
int dr[maxn] = {0};     // 存储10进制
int drans[maxn] = {0};  // 存储10进制转2进制的过程中的商,并且存储将 2 进制转换到 10 进制的过程中 的2^n
int drres[maxn] = {0};  // 存储10进制转2进制的过程中的余数

// 将 字符串 str 存到 dr int数组中, dr[0] 记录10进制数组长度
void change()
{
    memset(dr, 0, sizeof(dr));
    dr[0] = 0;      // 使用 dr[0] 存储数组长度
    for(int i = 1; i <= str.length(); ++i)
    {
        dr[++dr[0]] = str[i-1]-'0';
    }
}

// 将 10 进制转换成 2 进制
void solve()
{
    memset(drres, 0, sizeof(drres));

    int y, i, j, k;
    // 模 n 取余法,(总体规律是先余为低位,后余为高位)
    while(dr[0] >= 1)
    {
        // 只要被除数仍然 >= 1,则继续操作
        y = 0;
        i = 1;
        drans[0] = dr[0];       // 商的长度与被除数相同(包含前导0)
        while(i <= dr[0])
        {
            y = y * oldBase + dr[i];
            drans[i++] = y / newBase;
            y %= newBase;
        }
        drres[++drres[0]] = y;  // 本轮计算得到的余数
        i = 1;
        // 找到下一轮商的起始位置
        while((i<=drans[0]) && (drans[i] == 0)) ++i;
        // 清除这一轮使用的被除数
        memset(dr, 0, sizeof(dr));
        // 本轮得到的商为下一轮的被除数
        for(j = i; j <= drans[0]; ++j)
        {
            dr[++dr[0]] = drans[j];
        }
        // 清除本轮的商
        memset(drans, 0, sizeof(drans));
    }

    /**
        现在 drres 存储的是 str 的 2 进制的倒序,即题目中要求的二进制序列
        下面将 drres 中存储的 2 进制(1~drres[0]),转换成 10 进制并存储到 dr 中
    */
    memset(drans, 0, sizeof(drans));
    memset(dr,0,sizeof(dr));

    drans[0] = 1;
    drans[1] = 1;   // 2^0 = 1;
    for(i = drres[0]; i >= 1; --i)
    {
        // 先 + ,后计算 2 ^ n
        if(drres[i] == 1)
        {
            // dr[0] 取 dr[0] 原以及 drans[0] 取两者较大者,为了保持数据位数
            dr[0] = dr[0] > drans[0] ? dr[0] : drans[0];

            // 此为为 1 才加
            for(k = 1; k <= drans[0]; ++k)
            {
                dr[k] += drans[k];
            }
            // 移位
            for(j = 1; j <= dr[0]; ++j)
            {
                if(dr[j] > 9)
                {
                    dr[j+1] += dr[j] / oldBase;
                    dr[j] %= oldBase;
                    // 最高位进位的情况
                    if(dr[0] == j)
                    {
                        ++dr[0];
                    }
                }
            }
        }

        // 计算 2 ^ n
        for(j = 1; j <= drans[0]; ++j)
        {
            drans[j] *= newBase;
        }
        // 移位
        for(j = 1; j <= drans[0]; ++j)
        {
            if(drans[j] > 9)
            {
                drans[j+1] += drans[j] / oldBase;
                drans[j] %= oldBase;
                // 最高位进位的情况
                if(drans[0] == j)
                {
                    ++drans[0];
                }
            }
        }
    }

}

void output()
{
    for(int i = dr[0]; i > 0; --i)
    {
        cout << dr[i];
    }
}

int main()
{

    while(cin >> str)
    {
        change();       // 将10进制数据存储到数组中
        solve();        // 将 10 进制转换成 2 进制,并将其 2 进制倒序所表示的 10 进制存储到原数组中
        output();       // 输出
        cout << endl; 
    }

    return 0;
}

思路分析

  1. 由于输入有1000位,则应将初始输入存储到字符串中;
  2. 本解法采用模2取余的方法求输入数字的2进制表达形式;
  3. 2进制转换成10进制的过程中采用普通大数加法的形式;

赞(2)

draw : 回复 admin: 感谢大佬的解答,我们还没有学到这里,数据有点懵,但还是感谢大佬的不辞辛劳!

2019年11月28日 16:55