题意:给出正整数,确定其是否是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;
}