大家遇到很大的数都这么处理的

M阳光 2014-04-13 11:23:29
一道题:NYOJ 158

要求输出计算结果对2013求余后的数。

计算过程中涉及到排列组合(阶乘)。

当然不可能先计算出结果,再求余的~~
...全文
484 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
M阳光 2014-04-16
  • 打赏
  • 举报
回复
引用 19 楼 FancyMouse 的回复:
数据范围不说。组之间是否区分顺序也不说。这题够流氓的。
我觉得这道题不用关心数的范围额。。 任何数求余后都不会超过那个数的。。 也就是说,在计算的过程中只考虑最后几位就可以了。。。 不过,,这道题是有点流氓~~
FancyMouse 2014-04-16
  • 打赏
  • 举报
回复
引用 20 楼 M173475237 的回复:
[quote=引用 19 楼 FancyMouse 的回复:] 数据范围不说。组之间是否区分顺序也不说。这题够流氓的。
我觉得这道题不用关心数的范围额。。 任何数求余后都不会超过那个数的。。 也就是说,在计算的过程中只考虑最后几位就可以了。。。 不过,,这道题是有点流氓~~[/quote] 原来是我没看清楚,说了数据在int范围里。 2013没有平方因子那这题也简单好多。就是分别模3个p然后剩余定理组合起来而已。
FancyMouse 2014-04-15
  • 打赏
  • 举报
回复
数据范围不说。组之间是否区分顺序也不说。这题够流氓的。
如此美丽的你 2014-04-15
  • 打赏
  • 举报
回复
因为以前做过一道二分求幂的题,,也涉及到很大的数,要求输出MOD(ans)。用这个方法解决了: // (A*B)%M = ((A%M)*(B%M))%M // (b^14)%M = (b^8)%M * (b^4)%M * (b^2)%M // (b^8)%M = (b^4)%M * (b^4)%M // (b^4)%M = (b^2)%M * (b^2)%M // ... 所以,对于这道题,。我感觉也应该这样。
M阳光 2014-04-15
  • 打赏
  • 举报
回复
引用 16 楼 Inhibitory 的回复:
(b^4)%M = (b^2)%M * (b^2)%M 肯定不对:(3^4) % 10 = 1,如果用这个方法,则为 (3^2)%10 * (3^2)%10 = 81 实际上是 (a^n) % p = ((a%p)^n) % p
唔。。现在我想知道这道题怎么处理。。。
Inhibitory 2014-04-15
  • 打赏
  • 举报
回复
(b^4)%M = (b^2)%M * (b^2)%M 肯定不对:(3^4) % 10 = 1,如果用这个方法,则为 (3^2)%10 * (3^2)%10 = 81 实际上是 (a^n) % p = ((a%p)^n) % p
赵4老师 2014-04-14
  • 打赏
  • 举报
回复
学会使用GMP库?
M阳光 2014-04-14
  • 打赏
  • 举报
回复
引用 1 楼 FancyMouse 的回复:
2013=3*11*61 如果需要用除法的话那就分别mod上面3个数然后中国剩余定理组合起来。
引用 4 楼 FancyMouse 的回复:
[quote=引用 2 楼 Inhibitory 的回复:] [quote=引用 1 楼 FancyMouse 的回复:] 2013=3*11*61 如果需要用除法的话那就分别mod上面3个数然后中国剩余定理组合起来。
感觉能直接mod 3, 11, 6 那么直接mod 2013也没太大问题[/quote] 2013不是质数,除法不一定做得了。[/quote] 2013没什么问题,,直接求余就可以了,主要是因为算出的结果很大,而且计算过程中也可能涉及到很大的数,不知道具体有多大。 所以,我感觉应该用这样一个公式:(a*b)%M= ( (a%M)*(b%M) )%M.. 只是我具体实现的时候出问题了。。
赵4老师 2014-04-14
  • 打赏
  • 举报
回复
#include <iostream>
#include <string>
using namespace std;
inline int compare(string str1,string str2) {//相等返回0,大于返回1,小于返回-1
         if (str1.size()>str2.size()) return 1; //长度长的整数大于长度小的整数
    else if (str1.size()<str2.size()) return -1;
    else                              return str1.compare(str2); //若长度相等,则头到尾按位比较
}
string SUB_INT(string str1,string str2);
string ADD_INT(string str1,string str2) {//高精度加法
    int sign=1; //sign 为符号位
    string str;
    if (str1[0]=='-') {
        if (str2[0]=='-') {
            sign=-1;
            str=ADD_INT(str1.erase(0,1),str2.erase(0,1));
        } else {
            str=SUB_INT(str2,str1.erase(0,1));
        }
    } else {
        if (str2[0]=='-') {
            str=SUB_INT(str1,str2.erase(0,1));
        } else { //把两个整数对齐,短整数前面加0补齐
            string::size_type L1,L2;
            int i;
            L1=str1.size();
            L2=str2.size();
            if (L1<L2) {
                for (i=1;i<=L2-L1;i++) str1="0"+str1;
            } else {
                for (i=1;i<=L1-L2;i++) str2="0"+str2;
            }
            int int1=0,int2=0; //int2 记录进位
            for (i=str1.size()-1;i>=0;i--) {
                int1=(int(str1[i])-'0'+int(str2[i])-'0'+int2)%10;
                int2=(int(str1[i])-'0'+int(str2[i])-'0'+int2)/10;
                str=char(int1+'0')+str;
            }
            if (int2!=0) str=char(int2+'0')+str;
        }
    }
    //运算后处理符号位
    if ((sign==-1)&&(str[0]!='0')) str="-"+str;
    return str;
}
string SUB_INT(string str1,string str2) {//高精度减法
    int sign=1; //sign 为符号位
    string str;
    int i,j;
    if (str2[0]=='-') {
        str=ADD_INT(str1,str2.erase(0,1));
    } else {
        int res=compare(str1,str2);
        if (res==0) return "0";
        if (res<0) {
            sign=-1;
            string temp =str1;
            str1=str2;
            str2=temp;
        }
        string::size_type tempint;
        tempint=str1.size()-str2.size();
        for (i=str2.size()-1;i>=0;i--) {
            if (str1[i+tempint]<str2[i]) {
                j=1;
                while (1) {//zhao4zhong1添加
                    if (str1[i+tempint-j]=='0') {
                        str1[i+tempint-j]='9';
                        j++;
                    } else {
                        str1[i+tempint-j]=char(int(str1[i+tempint-j])-1);
                        break;
                    }
                }
                str=char(str1[i+tempint]-str2[i]+':')+str;
            } else {
                str=char(str1[i+tempint]-str2[i]+'0')+str;
            }
        }
        for (i=tempint-1;i>=0;i--) str=str1[i]+str;
    }
    //去除结果中多余的前导0
    str.erase(0,str.find_first_not_of('0'));
    if (str.empty()) str="0";
    if ((sign==-1) && (str[0]!='0')) str ="-"+str;
    return str;
}
string MUL_INT(string str1,string str2) {//高精度乘法
    int sign=1; //sign 为符号位
    string str;
    if (str1[0]=='-') {
        sign*=-1;
        str1 =str1.erase(0,1);
    }
    if (str2[0]=='-') {
        sign*=-1;
        str2 =str2.erase(0,1);
    }
    int i,j;
    string::size_type L1,L2;
    L1=str1.size();
    L2=str2.size();
    for (i=L2-1;i>=0;i--) { //模拟手工乘法竖式
        string tempstr;
        int int1=0,int2=0,int3=int(str2[i])-'0';
        if (int3!=0) {
            for (j=1;j<=(int)(L2-1-i);j++) tempstr="0"+tempstr;
            for (j=L1-1;j>=0;j--) {
                int1=(int3*(int(str1[j])-'0')+int2)%10;
                int2=(int3*(int(str1[j])-'0')+int2)/10;
                tempstr=char(int1+'0')+tempstr;
            }
            if (int2!=0) tempstr=char(int2+'0')+tempstr;
        }
        str=ADD_INT(str,tempstr);
    }
    //去除结果中的前导0
    str.erase(0,str.find_first_not_of('0'));
    if (str.empty()) str="0";
    if ((sign==-1) && (str[0]!='0')) str="-"+str;
    return str;
}
string DIVIDE_INT(string str1,string str2,int flag) {//高精度除法。flag==1时,返回商; flag==0时,返回余数
    string quotient,residue; //定义商和余数
    int sign1=1,sign2=1;
    if (str2 == "0") {  //判断除数是否为0
        quotient= "ERROR!";
        residue = "ERROR!";
        if (flag==1) return quotient;
        else         return residue ;
    }
    if (str1=="0") { //判断被除数是否为0
        quotient="0";
        residue ="0";
    }
    if (str1[0]=='-') {
        str1   = str1.erase(0,1);
        sign1 *= -1;
        sign2  = -1;
    }
    if (str2[0]=='-') {
        str2   = str2.erase(0,1);
        sign1 *= -1;
    }
    int res=compare(str1,str2);
    if (res<0) {
        quotient="0";
        residue =str1;
    } else if (res == 0) {
        quotient="1";
        residue ="0";
    } else {
        string::size_type L1,L2;
        L1=str1.size();
        L2=str2.size();
        string tempstr;
        tempstr.append(str1,0,L2-1);
        for (int i=L2-1;i<L1;i++) { //模拟手工除法竖式
            tempstr=tempstr+str1[i];
            tempstr.erase(0,tempstr.find_first_not_of('0'));//zhao4zhong1添加
            if (tempstr.empty()) tempstr="0";//zhao4zhong1添加
            for (char ch='9';ch>='0';ch--) { //试商
                string str;
                str=str+ch;
                if (compare(MUL_INT(str2,str),tempstr)<=0) {
                    quotient=quotient+ch;
                    tempstr =SUB_INT(tempstr,MUL_INT(str2,str));
                    break;
                }
            }
        }
        residue=tempstr;
    }
    //去除结果中的前导0
    quotient.erase(0,quotient.find_first_not_of('0'));
    if (quotient.empty()) quotient="0";
    if ((sign1==-1)&&(quotient[0]!='0')) quotient="-"+quotient;
    if ((sign2==-1)&&(residue [0]!='0')) residue ="-"+residue ;
    if (flag==1) return quotient;
    else         return residue ;
}
string DIV_INT(string str1,string str2) {//高精度除法,返回商
    return DIVIDE_INT(str1,str2,1);
}
string MOD_INT(string str1,string str2) {//高精度除法,返回余数
    return DIVIDE_INT(str1,str2,0);
}
int main() {
    char ch;
    string s1,s2,res;

    while (cin>>s1>>ch>>s2) {
        switch (ch) {
            case '+':res=ADD_INT(s1,s2);break;
            case '-':res=SUB_INT(s1,s2);break;
            case '*':res=MUL_INT(s1,s2);break;
            case '/':res=DIV_INT(s1,s2);break;
            case '%':res=MOD_INT(s1,s2);break;
            default :                   break;
        }
        cout<<res<<endl;
    }
    return(0);
}
  • 打赏
  • 举报
回复
好像很复杂的样子。
FancyMouse 2014-04-14
  • 打赏
  • 举报
回复
引用 2 楼 Inhibitory 的回复:
[quote=引用 1 楼 FancyMouse 的回复:] 2013=3*11*61 如果需要用除法的话那就分别mod上面3个数然后中国剩余定理组合起来。
感觉能直接mod 3, 11, 6 那么直接mod 2013也没太大问题[/quote] 2013不是质数,除法不一定做得了。
  • 打赏
  • 举报
回复
如果单纯操作大数,这里有一个:http://download.csdn.net/detail/zjq9931/6213983
Inhibitory 2014-04-14
  • 打赏
  • 举报
回复
引用 1 楼 FancyMouse 的回复:
2013=3*11*61 如果需要用除法的话那就分别mod上面3个数然后中国剩余定理组合起来。
感觉能直接mod 3, 11, 6 那么直接mod 2013也没太大问题
M阳光 2014-04-14
  • 打赏
  • 举报
回复
引用 14 楼 nice_cxf 的回复:
你想简单了,如果不用大数,必须要保证做 除法之前不能做取模运算,从给的数据的范围来看,这样的话避免不了大数 因此这题就是用大数来处理就可以了
多大的数可以储存2000! ? 题目中出现的数据可能比这还大。 因为以前做过一道二分求幂的题,,也涉及到很大的数,要求输出MOD(ans)。用这个方法解决了: // (A*B)%M = ((A%M)*(B%M))%M // (b^14)%M = (b^8)%M * (b^4)%M * (b^2)%M // (b^8)%M = (b^4)%M * (b^4)%M // (b^4)%M = (b^2)%M * (b^2)%M // ... 所以,对于这道题,。我感觉也应该这样。 但根据我的调试结果看来,在求余的过程中出现了结果等于0的情况,结果发生了除零错误。。
nice_cxf 2014-04-14
  • 打赏
  • 举报
回复
你想简单了,如果不用大数,必须要保证做 除法之前不能做取模运算,从给的数据的范围来看,这样的话避免不了大数 因此这题就是用大数来处理就可以了
M阳光 2014-04-14
  • 打赏
  • 举报
回复
引用 1 楼 FancyMouse 的回复:
2013=3*11*61 如果需要用除法的话那就分别mod上面3个数然后中国剩余定理组合起来。
能再说的详细点么? 万分感谢
FancyMouse 2014-04-14
  • 打赏
  • 举报
回复
2013=3*11*61 如果需要用除法的话那就分别mod上面3个数然后中国剩余定理组合起来。
M阳光 2014-04-14
  • 打赏
  • 举报
回复
引用 11 楼 zjq9931 的回复:
[quote=引用 10 楼 M173475237 的回复:] 我没表达清楚。。: 根据题中的问题来计算的话,算出的结果很大,可能会远远超出long long ..但是,题目并不要求输出那个大数,只要求输入那个大数对2013取余后的结果。
最好能看一下原题。 也有可能可以得出结论。 大数还有一个办法是用字符数组表示,没个元素代表一位。[/quote] 原题链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=158 是可以用字符数组,但是这道题没有这个必要。
  • 打赏
  • 举报
回复
引用 10 楼 M173475237 的回复:
我没表达清楚。。: 根据题中的问题来计算的话,算出的结果很大,可能会远远超出long long ..但是,题目并不要求输出那个大数,只要求输入那个大数对2013取余后的结果。
最好能看一下原题。 也有可能可以得出结论。 大数还有一个办法是用字符数组表示,没个元素代表一位。
M阳光 2014-04-14
  • 打赏
  • 举报
回复
我没表达清楚。。: 根据题中的问题来计算的话,算出的结果很大,可能会远远超出long long ..但是,题目并不要求输出那个大数,只要求输入那个大数对2013取余后的结果。
加载更多回复(1)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧