本文主要是介绍数论风骚套路汇总(不定期更新),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 10.30日更新(多项莫比乌斯反演)
- 10.31日更新
数论这个东西,确实值得深刻的研究。这里专门开一篇博客,记录遇见的一些奇技淫巧,一些妖艳的操作。(不定期更新)
10.30日更新(多项莫比乌斯反演)
求 ∑ i = 1 a 1 ∑ j = 1 a 2 … … ∑ x = 1 a x g c d ( i , j … … , x ) \sum_{i=1}^{a_1}\sum_{j=1}^{a_2}……\sum_{x=1}^{a_x}gcd(i,j……,x) ∑i=1a1∑j=1a2……∑x=1axgcd(i,j……,x)其中循环的 ∑ \sum ∑最多有10个。
这道题看上去很不可做,但实际上跟BZOJ2005这道题的本质和推法是一样的。
设 m i n min min是 a 1 … … a x a_1……a_x a1……ax中的最小值
∑ i = 1 a 1 ∑ j = 1 a 2 … … ∑ x = 1 a x g c d ( i , j … … , x ) = = ∑ i = 1 a 1 ∑ j = 1 a 2 … … ∑ x = 1 a x ∑ k = 1 m i n k ∗ [ g c d ( i , j … … , x ) = k ] \sum_{i=1}^{a_1}\sum_{j=1}^{a_2}……\sum_{x=1}^{a_x}gcd(i,j……,x)==\sum_{i=1}^{a_1}\sum_{j=1}^{a_2}……\sum_{x=1}^{a_x}\sum_{k=1}^{min}k*[gcd(i,j……,x)=k] ∑i=1a1∑j=1a2……∑x=1axgcd(i,j……,x)==∑i=1a1∑j=1a2……∑x=1ax∑k=1mink∗[gcd(i,j……,x)=k]
= ∑ k = 1 m i n k ∗ ∑ i = 1 a 1 k ∑ j = 1 a 2 k … … ∑ x = 1 a x k [ g c d ( i , j … … , x ) = 1 ] = = ∑ k = 1 m i n k ∗ ∑ i = 1 a 1 k ∑ j = 1 a 2 k … … ∑ x = 1 a x k ∑ x ∣ g c d ( i , j … … , x ) μ ( x ) =\sum_{k=1}^{min}k*\sum_{i=1}^{\frac{a_1}{k}}\sum_{j=1}^{\frac{a_2}{k}}……\sum_{x=1}^{\frac{a_x}{k}}[gcd(i,j……,x)=1]==\sum_{k=1}^{min}k*\sum_{i=1}^{\frac{a_1}{k}}\sum_{j=1}^{\frac{a_2}{k}}……\sum_{x=1}^{\frac{a_x}{k}}\sum_{x|gcd(i,j……,x)}\mu(x) =∑k=1mink∗∑i=1ka1∑j=1ka2……∑x=1kax[gcd(i,j……,x)=1]==∑k=1mink∗∑i=1ka1∑j=1ka2……∑x=1kax∑x∣gcd(i,j……,x)μ(x)
= ∑ k = 1 m i n k ∗ ∑ x = 1 m i n k μ ( x ) [ a 1 k x ] [ a 2 k x ] … … [ a x k x ] = = ∑ k = 1 m i n k ∗ [ a 1 k ] [ a 2 k ] … … [ a x k ] φ ( k ) =\sum_{k=1}^{min}k*\sum_{x=1}^{\frac{min}{k}}\mu(x)[\frac{a_1}{kx}][\frac{a_2}{kx}]……[\frac{a_x}{kx}]==\sum_{k=1}^{min}k*[\frac{a_1}{k}][\frac{a_2}{k}]……[\frac{a_x}{k}]φ(k) =∑k=1mink∗∑x=1kminμ(x)[kxa1][kxa2]……[kxax]==∑k=1mink∗[ka1][ka2]……[kax]φ(k)
于是就可以开心的数论分块喽!
#include<bits/stdc++.h>
#define MAXN 1000005
#define inf 2147483647
#define ll long long
using namespace std;
const ll MD=1e9+7;
ll read(){char c;ll x;while(c=getchar(),c<'0'||c>'9');x=c-'0';while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';return x;
}
ll T,n,i,s,top,l,r,Min,ans,a[15],vis[MAXN],pri[MAXN],phi[MAXN],sum[MAXN];
void pre(){vis[1]=1;phi[1]=1;sum[1]=1;for(ll i=2;i<=1000000;i++){if(!vis[i]) pri[++top]=i,phi[i]=i-1;for(ll j=1;j<=top&&i*pri[j]<=1000000;j++){vis[i*pri[j]]=1;if(i%pri[j]) phi[i*pri[j]]=phi[i]*phi[pri[j]]%MD;else{phi[i*pri[j]]=phi[i]*pri[j]%MD;break;}}sum[i]=sum[i-1]+phi[i];}
}
int main()
{T=read();pre();while(T--){n=read();l=1;ans=0;Min=2e9;for(ll i=1;i<=n;i++) a[i]=read(),Min=min(Min,a[i]);while(l<=Min){r=inf;s=1;for(ll i=1;i<=n;i++) {r=min(r,a[i]/(a[i]/l));s=(a[i]/l*s)%MD;}(ans+=(sum[r]-sum[l-1]+2*MD)%MD*s%MD)%MD;l=r+1;}printf("%lld\n",ans%MD);}return 0;
}
10.31日更新
设 f ( x ) = ∑ i = 1 ∞ ∑ j = 1 ∞ [ i ∗ j ∣ x ] f(x)=\sum_{i=1}^{\infty}\sum_{j=1}^{\infty}[i*j|x] f(x)=∑i=1∞∑j=1∞[i∗j∣x],求 ∑ i = 1 n f ( i ) \sum_{i=1}^{n}f(i) ∑i=1nf(i)
这道题的关键点就是转化,我们将条件转化,假设 x i ∗ j = k \frac{x}{i*j}=k i∗jx=k,那么我们求 f ( x ) f(x) f(x)只要枚举三元组 ( i , j , k ) (i,j,k) (i,j,k)即可。
我们先假设 a ≤ b ≤ c a\leq b\leq c a≤b≤c,那么我们 a a a从 1 1 1到 n 3 \sqrt[3]{n} 3n枚举, b b b从 a a a到 x a \sqrt{\frac{x}{a}} ax枚举,也就是for(ll a=1;a*a*a<=n;a++) for(ll b=a;a*b*b<=n;b++)
,那
么 c c c就可以取 [ b , n a ∗ b ] [b,\frac{n}{a*b}] [b,a∗bn],因为这样相乘都 ≤ n \leq n ≤n。于是用方案乘以这三元组倒换顺序的方案数即可。
核心代码,可以证明复杂度是 O ( n 2 3 ) O(n^{\frac{2}{3}}) O(n32),非常优秀。
for(ll a=1;a*a*a<=n;a++) for(ll b=a;a*b*b<=n;b++){ ll c=n/(a*b); if(c<b) break; if(a==b) ans+=(c-b)*3+1; else ans+=(c-b)*6+3; }
这篇关于数论风骚套路汇总(不定期更新)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!