码迷,mamicode.com
首页 > 其他好文 > 详细

HDU5780 gcd (BestCoder Round #85 E) 欧拉函数预处理——分块优化

时间:2016-07-31 15:51:12      阅读:358      评论:0      收藏:0      [点我收藏+]

标签:

分析(官方题解):

技术分享

一点感想:

首先上面那个等式成立,然后就是求枚举gcd算贡献就好了,枚举gcd当时赛场上写了一发O(nlogn)的反演,写完过了样例,想交发现结束了

吐槽自己手速慢,但是发了题解后发现,这题连O(n)欧拉函数前缀和的都卡了,幸亏没交,还是太年轻

 

对于官方题解说sqrt(n)优化(其实就是n/(小于n一段数)结果是一样的,也不算什么分块),还是很简单的,做反演题的时候看到过很多,只是忘记了

如果不会请看这篇解题报告http://wenku.baidu.com/view/fbe263d384254b35eefd34eb.html

 

细节处理:注意特判x=1的情况,然后处理(x-1)的逆元,等比数列求和需要用,感觉这题还是能做出来的

技术分享
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
typedef  long long LL;
const int N = 1e6+5;
const LL mod = 1e9+7;
int phi[N],T;
LL sum[N],x,n;
LL qpow(LL a,LL b){
  LL ret=1;
  while(b){
    if(b&1)ret=(ret*a)%mod;
    b>>=1;
    a=(a*a)%mod;
  }
  return ret;
}
inline void up(LL &x,LL y){
  x+=y;if(x>=mod)x-=mod;
}
int main(){
  phi[1]=1;
  for(int i=2;i<=N-5;++i)if(!phi[i]){
    for(int j=i;j<=N-5;j+=i){
      if(!phi[j])phi[j]=j;
        phi[j]=phi[j]/i*(i-1);
    }
  }
  for(int i=1;i<=N-5;++i)sum[i]=sum[i-1]+1ll*phi[i];
  scanf("%d",&T);
  while(T--){
    scanf("%I64d%I64d",&x,&n);
    if(x==1){
      printf("0\n");continue;
    }
    LL inv=qpow(x-1,mod-2),ret=0;
    for(int i=1,j;i<=n;i=j+1){
      j=n/(n/i);
      LL a0=qpow(x,i),qn=qpow(x,j-i+1);
      up(qn,mod-1);
      a0=a0*qn%mod*inv%mod;
      up(a0,mod-(j-i+1));
      a0=(2ll*sum[n/i]-1)%mod*a0%mod;
      up(ret,a0);
    }
    printf("%I64d\n",ret);
  }
  return 0;
}
View Code

 

HDU5780 gcd (BestCoder Round #85 E) 欧拉函数预处理——分块优化

标签:

原文地址:http://www.cnblogs.com/shuguangzw/p/5722965.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!