题目链接:http://codeforces.com/gym/101981/attachments

题意:

令 $mul(l,r) = \prod_{i=l}^{r}a_i$,且 $fac(l,r)$ 代表 $mul(l,r)$ 的不同素因子个数。求 $\sum_{i=1}^{n}\sum_{j=i}^{n}fac(i,j)$。

Input
The first line contains one integer n (1 \le n \le 10^6) — the length of the sequence.
The second line contains n integers ai (1 \le i \le n, 1 \le a_i \le 10^6) — the sequence.

Output
Print the answer to the equation.

Examples
standard input
10
99 62 10 47 53 9 83 33 15 24

standard output
248

standard input
10
6 7 5 5 4 9 9 1 8 12

standard output

134

题解:

考虑每个质因子对于整体答案的贡献。

拿第二组样例算一算就不难发现:第 $p$ 个位置上的数,其包含的任意一个素因子,它原本应当产生的贡献有 $(n-p+1) \cdot p$,

但是考虑到若其前面出现过一样的素数,那么应当减去一些重复计算的区间。假设它前面的和它一样的素数,最后一次出现在 $q$ 位置,那么就应当减去 $(n-p+1) \cdot q$,即 $a[p]$ 包含的任意一个质因子其产生的贡献为 $(n-p+1) \cdot p - (n-p+1) \cdot q = (n-p+1) \cdot (p - q)$。

不妨用 $pos[i][k]$ 来存储每个素因子的 “$p$”,$pos[i][k-1]$ 存储每个素因子的 “$q$”。换句话说,$pos[i][k]$ 代表某个素因子 $i$ 在 $a[1 \sim n]$ 中第 $k$ 次“出现”的位置是 $pos[i][k]$;特别地,令 $pos[i][0]=0$。那么对于任意素因子 $i$,它对答案的贡献是 $(n-pos[i][k]+1) \cdot (pos[i][k]-pos[i][k-1])$。

我们可以对 $a[1 \sim n]$ 分解质因数,然后更新相应的 $pos[i][k]$。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+; int n,a[maxn];
vector<int> pos[maxn];
void dec(int p)
{
int n=a[p];
for(int i=;i*i<=n;i++)
{
if(n%i==)
{
pos[i].push_back(p);
while(n%i==) n/=i;
}
}
if(n>) pos[n].push_back(p);
}
int main()
{
for(int i=;i<maxn;i++) pos[i].push_back(); scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
dec(i);
} ll ans=;
for(int i=;i<maxn;i++)
{
for(int k=;k<pos[i].size();k++)
ans+=(ll)(n-pos[i][k]+)*(pos[i][k]-pos[i][k-]);
}
cout<<ans<<endl;
}

分解质因数板子:

vector<int> dec(int n)
{
vector<int> p;
for(int i=;i*i<=n;i++)
{
if(n%i==)
{
p.push_back(i);
while(n%i==) n/=i;
}
}
if(n>) p.push_back(n);
return p;
}

交了一发,大概700ms多点过了,那我们能否加快一下速度呢?

我们可以先用线性筛筛出 $[1,1e6]$ 的素数,然后再做分解质因数:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+; int n,a[maxn];
vector<int> pos[maxn]; const int MAX=1e6;
int tot,prime[MAX/];
bool isPrime[MAX+];
void Screen() //欧拉筛
{
tot=;
memset(isPrime,,sizeof(isPrime));
isPrime[]=isPrime[]=;
for(int i=;i<=MAX;i++)
{
if(isPrime[i]) prime[tot++]=i;
for(int j=;j<tot;j++)
{
if(i*prime[j]>MAX) break;
isPrime[i*prime[j]]=;
if(i%prime[j]==) break;
}
}
} void dec(int p)
{
int n=a[p];
for(int i=;i<tot && prime[i]*prime[i]<=n;i++)
{
if(n%prime[i]==)
{
pos[prime[i]].push_back(p);
while(n%prime[i]==) n/=prime[i];
}
}
if(n>) pos[n].push_back(p);
}
int main()
{
Screen();
for(int i=;i<tot;i++) pos[prime[i]].push_back(); scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
dec(i);
} ll ans=;
for(int i=;i<tot;i++)
{
for(int k=;k<pos[prime[i]].size();k++)
ans+=(ll)(n-pos[prime[i]][k]+)*(pos[prime[i]][k]-pos[prime[i]][k-]);
}
printf("%I64d\n",ans);
}

跑了大概400ms,还是快了不少的。

最新文章

  1. 学习.NET是因为热爱 or 兴趣 or 挣钱?
  2. javascript总结
  3. Encapsulation、Inheritance、Polymorphism
  4. Dictionary&lt;TKey, TValue&gt; 类
  5. Webbench网站压力测试
  6. replace() replace_copy()
  7. java中对象的序列化和反序列化
  8. 现代程序设计——homework-08
  9. NCPC 2012 Bread Sorting
  10. python 中去除BOM头
  11. 自适应的tab菜单栏
  12. java 多线程Callable和Runable执行顺序问题详解
  13. 201521123048 《Java程序设计》第5周学习总结
  14. USACO Section 2.1 The Castle
  15. Java基础知识➣集合整理(三)
  16. 让WebBrowser在非兼容模式下运行
  17. iOS常用小功能
  18. [leetcode]Interleaving String @ Python
  19. Use Reentrant Functions for Safer Signal Handling(译:使用可重入函数进行更安全的信号处理)
  20. Apache-Shiro介绍

热门文章

  1. JSP简单练习-猜字母游戏
  2. RobotFrameWork编写接口测试及如何断言
  3. 51单片机stack堆栈
  4. 开源一个CSV解析器(附设计过程 )
  5. IPv6地址分类及表示方法
  6. Nuxt.js部署应用的方式
  7. 利用final定义方法:这样的方法为一个不可覆盖的方法。
  8. MySQL yum 在线与本地包方式安装
  9. Kubernetes集群部署之五node节点部署
  10. javascript转义unicode十六进制编码且带有反斜杠后的html