NOI 能量采集

 1 /**
 2 大意: 求解 在[1,n] x,  [1,m] y,之间有多少个gcd(x,y) = d   d = min(n,m)
 3 思路: 对于任意一个d   在[1,n] x,  [1,m] y, gcd(x,y) 含有d 因子的个数为 n/i * m/i  这是所有含有因子d的组合的个数 , 再减去 gcd(x,y) = 2*d  , gcd(x,y) = 3*d, gcd(x,y) = 4*d。。。那么最后得到的就是最大公约数为d的组合的个数
 4 
 5 siga( 1-n  )  * siga(1-m)  2* (gcd(x,y)-1) + 1 ===>siga( 1-n(x)  )  * siga(1-m(y))  2* (gcd(x,y)-1) + n*m
 6 **/
 7 #include <iostream>
 8 #include <algorithm>
 9 #include <cstring>
10 using namespace std;
11 
12 long long cnt[100050];
13 
14 int main()
15 {
16     long long n,m;
17     while(cin>>n>>m){
18         memset(cnt,0,sizeof(cnt));
19         int t = min(n,m);
20         for(int i=2;i<=t;i++)
21             cnt[i] = (n/i)*(m/i);
22         for(int i=t;i>=1;i--){
23             for(int k=2;k*i<=t;k++)
24                 cnt[i] -= cnt[i*k];
25         }
26         long long ans =0;
27         for(int i=1;i<=t;i++)
28             ans += 2*(i-1)*cnt[i];
29         ans += n*m;
30         cout<<ans<<endl;
31     }
32     return 0;
33 }

 

posted @ 2014-05-12 20:10  夜晓楼  阅读(223)  评论(0编辑  收藏  举报