`
kmplayer
  • 浏览: 512741 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

国际大学生程序设计竞赛例题_1.2 求和

J# 
阅读更多
题目大意:
不计进位的加法,进制范围:2到16
例如:
55 67
十进制:55 add 67=12
二进制:110111 add 1001100=1111011=123

输入:
2 10 //两个区域,十进制加
3 6
9 15
输出:
从3到6 加上 从9到15的和

解答:
#include <iostream>
using namespace std;

#define MAX_SCALE 16 //最大进制数
#define LEN 32 //最大位数

unsigned int a[LEN],b[LEN]; //加数与被加数给位上的数

void add(unsigned int& x, unsigned int y, int m) //m进制不进位加法
{
    x = (x+y)%m;
}

void calc(unsigned int x, unsigned int m, unsigned int b[]) //求m进制下sum(0:x),结果存储在b
{
    int i,j,k;
    for(i=0; i<LEN; i++) b[i]=0;
    if(x==0) return; //结果为0

    unsigned int c[LEN][MAX_SCALE];//c[i][j]:第i为上数字j出现的次数
    unsigned int d[LEN]; //d[i]为m^i
    unsigned int digit[LEN];//digit[i]为x的第i为数字

    unsigned int temp=x; //计算digit[]数组
    unsigned int nDigit=0; //保存位数
    while(temp>0)
    {
        digit[nDigit++] = temp%m;
        temp /= m;
    }

    //计算d[]数组
    d[0]=1;
    for(i=1; i<nDigit; i++)
        d[i] = d[i-1]*m;

    //初始化c[][]数组
    for(i=nDigit-1; i>=0; i--)
        for(j=0; j<MAX_SCALE; j++)
            c[i][j] = 0;

    //由高位到低位计算c数组
    for(i=nDigit-1; i>=0; i--)
    {
        for(j=0; j<digit[i]; j++)
            add(c[i][j], d[i], m); //数字0-digit[i-1],出现了M^i次.
        add(c[i][digit[i]], x%d[i]+1, m); //数字digit[i],出现了x%(M^i)+1次

        for(j=i-1; j>=0; j--)
            for(k=0; k<m; k++)
                add(c[j][k], digit[i]*d[i-1], m); //低位上每个数字出现digit[i]*(M^(i-1))次
    }

    for(i=0; i<nDigit; i++)
    {
        b[i]=0;
        for(j=0; j<m; j++)
            add(b[i], c[i][j]*j, m);
    }
}
int main()
{
    freopen("1.2.in", "r", stdin);
    int T;//数据组数
    int n,m;//区间数与进制数
    unsigned int x,y,ans;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &n, &m);
        memset(a, 0, sizeof(a)); //保存最后结果
        while(n--)
        {
            scanf("%u%u", &x,&y); //输入区间[x,y]
            calc(y, m, b); //计算sum(0:y)
            for(int i=0; i<LEN; i++)
                a[i] = (a[i]+b[i])%m; //实际上就是把b[i]赋值给a[i]
            if(x>0)
            {
                calc(x-1, m, b); //计算sum[0:x-1]
                for(int i=0; i<LEN; i++)
                    a[i] = (a[i]-b[i]+m)%m; //sum[x:y]=sum[0:y]-sum[0:x-1]
            }
        }
        ans = 0; //保存十进制结果
        for(int i=LEN-1; i>=0; i--)
            ans = ans*m+a[i];
        printf("%u\n",ans);
    }
    return 0;
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics