1. 程式人生 > >模運算(附加幾種資料型別的資料範圍判斷)-hdu3123

模運算(附加幾種資料型別的資料範圍判斷)-hdu3123

題目連結: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 }