模運算(附加幾種資料型別的資料範圍判斷)-hdu3123
阿新 • • 發佈:2018-11-22
題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=3123
預備知識點:
(a+b)%m=[(a%m)+(b%m)]%m
(a*b)%m=[(a%m)*(b%m)]%m
所以(0!+1!+2!+.....+n!)%m=[(0!%m+1!%m)%m+(1!%m)*(2%m)%m}%m.........到K>=n時,K!%m=0
因為此題涉及大資料,因此去了解了一下C/C++語言中計算int,float,double,char四種資料型別所能表示的資料範圍:
詳見部落格:https://blog.csdn.net/wordwarwordwar/article/details/52558687
題目描述:
此題關鍵點在n的資料範圍為0~10^100,所以我用了兩種方法來處理此大資料:
1、利用char陣列來存大數n,實現大數相加
#include<stdio.h> #include<iostream> #include<cstring> using namespace std; char a[102]; int main() { int t; long long m,ans; scanf("%d",&t); while(t--) { ans=0; scanf("%s",a); scanf("%lld",&m); long long sum=0; int len=strlen(a); for(int i=0;i<len;i++) { sum=sum*10+(a[i]-'0'); if(sum>m) break; } if(sum>=m) { ans=m-1; for(int i=ans-1;i>=1;i--) { ans=(((ans+1)%m)*i%m)%m; } } else { ans=sum; for(int i=ans-1;i>=1;i--) ans=(((ans+1)%m)*i%m)%m; } printf("%lld\n",(ans+1)%m); } return 0; }
2、因為double型能表示的資料範圍在1.7 x 10^(-308)~ 1.7 x 10^(+308)之間,而n的範圍為0~10^100,所以可以利用double型來存大數n。
1 #include<stdio.h> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 int main() 6 { 7 int t; 8 double a; 9 long long m,ans; 10 scanf("%d",&t); 11 while(t--) 12 { 13 ans=0; 14 scanf("%lf%lld",&a,&m); 15 if(a>=m) 16 { 17 ans=m-1; 18 for(int i=ans-1;i>=1;i--) 19 { 20 ans=(((ans+1)%m)*i%m)%m; 21 } 22 } 23 else 24 { 25 ans=a; 26 for(int i=ans-1;i>=1;i--) 27 ans=(((ans+1)%m)*i%m)%m; 28 } 29 printf("%lld\n",(ans+1)%m); 30 } 31 return 0; 32 }