算是學會反演了……(其實挺好學的一天就能學會……ios
原題:ide
今天的數學課上,Crash小朋友學習了最小公倍數(Least Common Multiple)。對於兩個正整數a和b,LCM(a, b)表示能同時被a和b整除的最小正整數。例如,LCM(6, 8) = 24。回到家後,Crash還在想着課上學的東西,爲了研究最小公倍數,他畫了一張N*M的表格。每一個格子裏寫了一個數字,其中第i行第j列的那個格子裏寫着數爲LCM(i, j)。一個4*5的表格以下: 1 2 3 4 5 2 2 6 4 10 3 6 3 12 15 4 4 12 4 20 看着這個表格,Crash想到了不少能夠思考的問題。不過他最想解決的問題倒是一個十分簡單的問題:這個表格中全部數的和是多少。當N和M很大時,Crash就一籌莫展了,所以他找到了聰明的你用程序幫他解決這個問題。因爲最終結果可能會很大,Crash只想知道表格裏全部數的和mod 20101009的值。學習
反演嘛,直接推公式spa
(Atom和即時預覽的latex插件真好用插件
(治好了我多年的公式恐懼症~~(模仿po姐3d
而後按照莫比烏斯反演經典的計算方法for(int i=1,j;i<=n;i=j+1) j=min(n/(n/i),m/(m/i));O(√n*√n)=O(n)計算就能夠了code
須要注意的是由於計算過程當中是在模意義下計算的,因此會出現負數(可是由於計算是在模意義下進行的因此答案確實是對的),最後須要加模數再取模blog
(反演其實挺好學的一天就能學會(就學個反演都拖了一年我之前真是釷氧釷砷釙熵鈦鎿銥鎢ip
代碼:ci
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 #define ll long long 8 const int mo=20101009; 9 int rd(){int z=0,mk=1; char ch=getchar(); 10 while(ch<'0'||ch>'9'){if(ch=='-')mk=-1; ch=getchar();} 11 while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0'; ch=getchar();} 12 return z*mk; 13 } 14 void wt(int x){if(x<0) putchar('-'),x=-x; 15 int wtp=0; char wtc[22]; 16 while(x) wtc[++wtp]=(x%10)+'0',x/=10; 17 while(wtp) putchar(wtc[wtp--]); 18 } 19 int n,m; 20 int prm[11000000],prp=0,miu[11000000]; bool prg[11000000]; 21 int s[11000000]; 22 void gtmiu(){ 23 fill(prg+1,prg+n+1,0); 24 miu[1]=1; 25 for(int i=2;i<=n;++i){ 26 if(!prg[i]) prm[++prp]=i,miu[i]=-1; 27 for(int j=1;j<=prp && i*prm[j]<=n;++j){ 28 prg[i*prm[j]]=true; 29 if(!(i%prm[j])){ miu[i*prm[j]]=0; break;} 30 miu[i*prm[j]]=-miu[i]; 31 } 32 } 33 for(ll i=1;i<=n;++i) 34 s[i]=(s[i-1]+(i*i*miu[i])%mo)%mo; 35 } 36 ll sm(ll x,ll y){ return (((x*(x+1)/2)%mo)*((y*(y+1)/2)%mo))%mo;} 37 ll cclt(int x,int y){ 38 if(x>y) swap(x,y); 39 ll bwl=0; 40 for(ll i=1,j;i<=x;i=j+1){ 41 j=min(x/(x/i),y/(y/i)); 42 bwl=(bwl+((s[j]-s[i-1])*sm(x/i,y/i))%mo)%mo; 43 } 44 return bwl; 45 } 46 int main(){//freopen("ddd.in","r",stdin); 47 cin>>n>>m; 48 if(n>m) swap(n,m); 49 gtmiu(); 50 ll ans=0; 51 for(ll i=1,j;i<=n;i=j+1){ 52 j=min(n/(n/i),m/(m/i)); 53 ans=(ans+(((i+j)*(j-i+1)/2)%mo*cclt(n/i,m/i))%mo)%mo; 54 } 55 cout<<(ans+mo)%mo<<endl; 56 return 0; 57 }