十二届 - CSU 1803 :2016(同余定理)

题目地址:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1803 

 

Knowledge Point:

  同余定理:两个整数a、b,若它们除以整数m所得的余数相等,则称a与b对模m同余或a同余于b模m。记作 a≡b(mod m)

    加法运用: (a + b) % m = (a % m + b % m) % m

 

    乘法运用: (a * b) % m = ((a % m) * (b % m)) % m

 

 

     高精度取模: 一个高精度数对一个数取余,可以把高精度数看成各位数的权值与个位数乘积的和。

          eg: 1234  = ((1*10+2) *10+3) *10+4, 综合运用上面的加法和乘法运用公式求解;

1 string a = "1234";
2 int ans = 0;
3 for(int i = 0; i < a.length; i++){
4     ans = (ans * 10 + a[i] - '0') % mod;
5 }
6 cout << ans << endl;

 

     快速幂取模:  将幂拆解为多个底数的平方次的积,如果指数为偶数,把指数除以2,并让底数的平方次取余,如果指数为奇数,就把多出来的底数记录下来,再执行偶数次的操作。

 1 int PowerMod(int a, int b, int mod){
 2     int ans = 1;    //a-底数,b-质数
 3     a = a % mod;   
 4     while(b > 0){
 5         if(b&1){
 6             ans *= (a % mod);
 7         }
 8         b >>= 1;
 9         a = (a * a) % mod;
10     }
11     ans %= mod;
12     return ans;
13 }

 

 

Summarize

  1. 同余定理运用;

  2. 数据范围爆 int,使用 long long;

  3. 如果 (i*j)%mod==0 则有 (i*j+mod)%mod==0 ;

 

  一开始我选择求2016的所有因数,循环将 n 和 m 中因数的倍数个数相乘再将所有结果相加。但可能出现某一个数 x 同时是多个因数的公倍数,且

2016/x 恰好也是多个因数的公倍数,出现重复,故该方法不能通过。

 

附代码:

 1 /*
 2 题目地址:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1803 
 3 
 4 2016
 5 给出正整数 n 和 m,统计满足以下条件的正整数对 (a,b) 的数量:
 6     1. 1≤a≤n,1≤b≤m;
 7     2. a×b 是 2016 的倍数。
 8 输入每组数据包含两个整数 n,m (1≤n,m≤10e9).
 9 
10 Sample Input
11 32 63
12 2016 2016
13 1000000000 1000000000
14 
15 Sample Output
16 1
17 30576
18 7523146895502644
19 */
20 #include<iostream>
21 #include<cstring>
22 #include<algorithm>
23 #include<vector>
24 #include<queue>
25 #include<cmath>
26 using namespace std;
27 
28 #define LL long long
29 const int N = 2016;
30 LL n,m,ans;
31 LL a[N], b[N];
32 
33 int main()
34 {
35     ios::sync_with_stdio(false);
36     
37     while(cin>>n>>m)
38     {
39         ans=0;
40         for(int i=0; i<N; i++)
41             { a[i]=n/N; b[i]=m/N;}
42         for(int i=1; i<=n%N; i++) a[i]++;
43         for(int i=1; i<=m%N; i++) b[i]++;
44 
45         for(int i=0; i<N; i++)
46             for(int j=0; j<N; j++)
47                 if(i*j%N == 0)
48                     ans += a[i]*b[j];
49         cout<<ans<<endl;
50     }
51     
52     return 0;
53 }

 

posted @ 2018-07-29 00:56  liubilan  阅读(244)  评论(0编辑  收藏  举报