[ Luogu 3935 ] Calculating

\(\\\)

\(Description\)


\(x\)分解质因数结果为\(x=p_1^{k_1}p_2^{k_2}\cdots p_n^{k_n}\),令\(f(x)=(k_1+1)(k_2+1)\cdots (k_n+1)\)

\(\sum_{i=l}^rf(i)\)\(998244353\)取模的结果。

  • \(l,r\in [1,10^{14}]\)

\(\\\)

\(Solution\)


首先要知道这里定义的 \(f\) 函数的值其实就是这个数的因数个数。

连乘的含义是容斥原理,考虑要构成的约数从每一个质因子里分别选取了多少个,所以有指数加一连乘的种类数。

然后所求就变成了区间内每个数的因子个数之和,问题可以转化为前缀相减。

然后考虑区间\([1,N]\)内所有数的因子个数之和,这个东西可以枚举这个因子是什么,即

\[ans=\sum_{d=1}^N \lfloor\frac{N}{d} \rfloor \]

然后就是除法分块的板子了。

\(\\\)

\(Code\)


#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define R register
#define gc getchar
#define N 4000010
using namespace std;
typedef long long ll;
 
inline ll rd(){
  ll x=0; bool f=0; char c=gc();
  while(!isdigit(c)){if(c=='-')f=1;c=gc();}
  while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
  return f?-x:x;
}
 
ll n,a[N];
int res,ans[N];
 
int main(){
  n=rd();
  for(R int i=1;i<=n;++i) a[i]=rd();
  for(R int i=1,r=1;i<=n;++i){
    if(r<i) r=i;
    while(r<n&&a[r+1]%a[i]==0) ++r;
    ans[i]=r;
  }
  for(R int i=n,l=n;i>0;--i){
    if(l>i) l=i;
    while(l>1&&a[l-1]%a[i]==0) --l;
    res=max(res,ans[i]-l+1);
  }
  printf("%d",res);
  return 0;
}
posted @ 2018-10-08 21:36  SGCollin  阅读(134)  评论(0编辑  收藏  举报