小A的數學題


小A最近開始研究數論題了,這一次他隨手寫出來一個式子,html

 

可是他發現他並不太會計算這個式子,你能夠告訴他這個結果嗎,答案可能會比較大,請模上1000000007。c++

輸入描述:

一行兩個正整數n,m一行兩個正整數n,mnm

輸出描述:

一行一個整數表示輸出結果一行一個整數表示輸出結果
示例1

輸入

複製
2 2

輸出

複製
7

備註1≤n,m≤1e61 \leq n,m \leq 1e61n題意:給定兩個數,n,m;求(1~n)(1~m)的 gcd(i,j)平方和


思路:簡單暴力確定超時,
看兩個數的最大公約數,咱們反過來求,從min(n,m)最大的可能公約數開始逐級遞減
從min(n,m)~1
令 p = min(n,m),
那麼在n裏面p的倍數有n/p個,即有n/p個數存在p這個約數
對於m而言也同樣;
以後再從 p*2開始將全部p的倍數再減掉,剩下的就是約數最大爲p的個數,即對於n,m而言就是gcd(n,m)==p的全部組合爲(n/p)*(m/p);

例子
n = 9, m= 7;
p = 7;
gcd(i,j) == 7;
f[7] = 1;
gcd(i,j)=6;
f[6]=1;
gcd(i,j) = 5;
f[5]=5;
gcd(i,j)=4;
f[4]=2;
gcd(i,j)=3;
f[3]=5;
gcd(i,j)=2;
f[2]=9;
f[1]=44;

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 typedef long long ll;
 5 const int N = 1e6+10;
 6 #define mod 1000000007
 7 ll n,m;
 8 ll num;
 9 ll f[N];
10 int main()
11 {
12     scanf("%lld%lld",&n,&m);
13     for(int i = min(n,m); i >=1;i--)
14     {
15         f[i] = (n / i) * (m / i);
16         for(int j = 2 * i; j <= min(n , m); j += i)
17         {
18             f[i] -= f[j];
19         }
20         //cout << f[i]<<' '<<i<<endl;
21         num = (num + f[i] * i % mod * i % mod )%mod;
22     }
23     cout << num <<endl;
24     return 0;
25 }
View Code
相關文章
相關標籤/搜索