You can say 11 UVA - 10929(数学)(大数模除)

传送门

题意:给出正整数,确定其是否是11的倍数

吴永辉老师给出了两种方法:

方法一:递推(感觉和长除法很想,模拟一个真实的除法)

设高精度整数位A=a(0).....a(l-1),前i位(a(0)....a(i))的余数为s(i);

s(0)=0;

s(i)=(s(i-1)*10+(ai对应的一位整数))%11(1<=i<=l-1)

显然,如果s(l-1)==0,则A是11的倍数,否则A非11的倍数。

方法二:利用奇偶数位差法

设a(n)a(n-1)...a(2)a(1)为n位整数且n为奇数(n为偶数类似),假设Y=11*a(n)a(n-1)...a(2)a(1)=10*a(n)a(n-1)...a(2)a(1)+a(n)a(n-1)...a(2)a(1)。

Y偶数位上的数位和为S,Y奇数位上的数位和为K。

显然S==K,即奇数位和偶数位的树和相等。

但这并没有考虑进位,如果有进位,设有m1个偶数位和m2个奇数位有进位(m1+m2<=n).m1个偶数位的进位分别加入了m1个奇数位,其结果是,偶数位和减少了10*m1,奇数位和加入了1*m1,这样奇数位数和偶数位数的差就减少了11*m1,同理,m2个奇数位点的进位加入了m2个偶数位,使得奇数位的数和减少了10*m2,偶数位的数和增加了1*m2,最终使得奇数位数的和与偶数位数和的差增加了11*m2.最终可以得到:A的奇数位数和与偶数位数的和的差是11的倍数(包括0)

//大数模除
#include<iostream>
#include<cstdio>

using namespace std;

const int maxn=1005;

char s[maxn];

int main()
{
    while(scanf("%s",s)&&(s[0]!='0'||s[1]!=0)){
        int sum=0;
        for(int i=0;s[i];i++){
            sum*=10;
            sum+=s[i]-'0';
            sum%=11;
        }
        printf("%s is %sa multiple of 11.\n",s,sum==0?"":"not ");
    }
    return 0;
}
//奇偶位差法
#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

const int maxn=1005;

char s[maxn];

int main()
{
    while(scanf("%s",s)!=EOF&&(s[0]!='0'||s[1]!='\0')){
        int len=strlen(s);
        int sum1=0,sum2=0;
        for(int i=0;i<len;i+=2){
            sum1+=s[i]-'0';
        }
        for(int i=1;i<len;i+=2){
            sum2+=s[i]-'0';
        }
        for(int i=0;i<len;i++){
            printf("%c",s[i]);
        }
        if((sum1-sum2)%11==0){
            printf(" is a multiple of 11.\n");
        }else{
            printf(" is not a multiple of 11.\n");
        }
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/80766235