Sicily 1195. Summation

本文介绍了一个特殊的编程问题——“无进位加法”。任务是在不同的数值系统中计算多个整数区间之和,并采用一种不考虑进位的加法规则。文章详细解释了问题背景、输入输出格式及示例。

1195. Summation

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

Just as the problem title indicates, your task is to calculate the sum of several integers. Really simple! Right? No, not that simple actually, because many things are different from the usual summation, the operator, the operands, and so on. Please look into the following details:  

 

       First, instead of the usual addition scheme, you should do “No Carry Addition” here. That means we should add two integers according to the usual addition scheme, but ignore the carry everywhere in the addition. For example, suppose we would like to calculate the sum of 55 and 76 in the decimal system, then under the usual addition scheme, the result will be 131; while under the “No Carry Addition” scheme, the result is 21. These processes are illustrated below:  

       Second, the addition can be performed in any base from 2 to 16. For example, given two decimal numbers 55 and 76, then if we perform No Carry Addition in the decimal system, the sum of them is 21(decimal), while in the binary system, the binary representation of 55 and 76 are 110111 and 1001100 respectively, so the sum of them will be 1111011(binary) = 123(decimal). 

     Third, the operands are given in the format of integer segments instead of single integers. As we know, integer segment [x, y] represents consecutive integers starting from x and ending at y, and the sum of two segments [x1, y1] and [x2, y2] is equal to the sum of all the integers in each segment. (If one integer is inside both segments, then it should be calculated twice).   

       Now we can reach the conclusion of the problem statement: Given several integer segments and a base from 2 to 16, your task is to calculate the sum of them according to the “No Carry Addition” Scheme. 

Input

Input contains several test cases. The first line is a single integer, T (1<=T<=20), the number of test cases followed. For each test case, the first line is two integers, N, M, (1<=N<=100, 2<=M<=16), N is the number of integer segments, and M is the base in which the summation should be performed. And then N lines follow. Each line of them contains two 32-bit unsigned integers, x and y, representing the integer segment [x, y] (x and y are both in decimal representation, and x<=y).

Output

For each test case, the output is one line containing a single 32-bit unsigned integer, representing the result in decimal format.

Sample Input

32 1055 5576 762 255 5576 763 20 38 164 7

Sample Output

2112316

Problem Source

ZSUACM Team Member

// Problem#: 1195
// Submission#: 3588448
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <stdio.h>
#include <string.h>

const int MAX_SCALE = 16;
const int LEN = 32;

unsigned int a[LEN], b[LEN];

void add(unsigned int & x, unsigned int y, int m) {x = (x + y) % m;}

void calc(unsigned int x, int m, unsigned int b[]) {
    int i, j, k;
    for (i = 0; i < LEN; i++) b[i] = 0;
    if (x == 0) return;
    unsigned int c[LEN][MAX_SCALE];
    unsigned int d[LEN], digit[LEN];
    int nDigit = 0;
    unsigned int temp = x;
    while (temp > 0) {
        digit[nDigit++] = temp % m;
        temp /= m;
    }
    d[0] = 1;
    for (i = 1; i < nDigit; i++) d[i] = d[i - 1] * m;
    for (i = nDigit - 1; i >= 0; i--)
        for (j = 0; j < m; j++) c[i][j] = 0;
    for (i = nDigit - 1; i >= 0; i--) {
        for (j = 0; j < digit[i]; j++) add(c[i][j], d[i], m);
        add(c[i][digit[i]], x % d[i] + 1, m);
        for (j = i - 1; j >= 0; j--)
            for (k = 0; k < m; k++) add(c[j][k], digit[i] * d[i - 1], m);
    }
    for (i = nDigit - 1; i >= 0; i--) {
        b[i] = 0;
        for (j = 0; j < m; j++) add(b[i], c[i][j] * j, m);
    }
}

int main() {
    int T, 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);
            calc(y, m, b);
            for (int i = 0; i < LEN; i++) a[i] = (a[i] + b[i]) % m;
            if (x > 0) {
                calc(x - 1, m, b);
                for (int i = 0; i < LEN; i++) a[i] = (a[i] + m - b[i]) % m;
            }
        }
        ans = 0;
        for (int i = LEN - 1; i >= 0; i--) ans = ans * m + a[i];
        printf("%u\n", ans);
    }
    return 0;
}                                 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值