HDU 6706 2019CCPC网络赛 1005 huntian oy(杜教筛)

HDU 6706 2019CCPC网络赛 1005 huntian oy(杜教筛)_第1张图片

HDU 6706 2019CCPC网络赛 1005 huntian oy(杜教筛)_第2张图片

 

 

大致题意:告诉你n、a和b,让你求

                          \large f(n,a,b)=\sum_{i=1}^n \sum_{j=1}^i gcd(i^a-j^a,i^b-j^b)[gcd(i,j)=1]\%(10^9+7)

中间那个gcd(i^a-j^a,i^b-j^b)这个看起来很吓人,其实你打表会发现其实它等于i-j,那么就变成了求

                                     \large f(n,a,b)=\sum_{i=1}^n \sum_{j=1}^i (i-j)[gcd(i,j)=1]\%(10^9+7)

这个显然可以拆成两个部分

                           \large f(n,a,b)=\sum_{i=1}^n \sum_{j=1}^i i[gcd(i,j)=1] -\sum_{i=1}^n \sum_{j=1}^ij[gcd(i,j)=1]

第一部分就是phi(i)的和,第二部分就是所有与i互质的小于i的数字的和,即

                            \large f(n,a,b)=\sum_{i=1}^n i*\phi(i) -\sum_{i=1}^n \frac{i*\phi(i)+[i=1]}{2}=\sum_{i=1}^n \frac{i*\phi(i)-1}{2}

利用杜教筛尝试求i*phi(i)的前缀和,我们令f(i)=i*phi(i),有

                                                            HDU 6706 2019CCPC网络赛 1005 huntian oy(杜教筛)_第3张图片

然后考虑开始求和

                          \large \begin{align*} \sum_{i=1}^{n} (f*id)(i)&=\sum_{i=1}^{n}i^2\\ \sum_{i=1}^{n}\sum_{i|j}f(i/j)*id(j)&=\frac{n(n+1)(2n+1)}{6}\\ \sum_{j=1}^{n}j\sum_{i=1}^{\lfloor\frac{n}{j}\rfloor}f(i)&=\frac{n(n+1)(2n+1)}{6}\\ \sum_{j=1}^{n}j*S(\lfloor n/j \rfloor)&=\frac{n(n+1)(2n+1)}{6}\\ S(n)&=\frac{n(n+1)(2n+1)}{6}-\sum_{j=2}^{n}j*S(\lfloor n/j \rfloor) \end{align*}

套上杜教筛即可,具体见代码:

#include
#define N 3333310
#define INF 0x3f3f3f3f
#define eps 1e-6
#define pi 3.141592653589793
#define mod 1000000007
#define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<"      :   "<
#include 
#include 
#include 
using namespace __gnu_pbds;
unordered_map mp;

const LL inv2=500000004;
const LL inv6=166666668;

int p[N],cnt,phi[N],psum[N],isp[N];
int vis[N];

void init()
{
    int sz=0;
    phi[1]=1;
    for(int i=2;i

 

你可能感兴趣的:(---------Online,Judge--------,HDU,CCPC,筛法)