题目:

洛谷2926

(截止至本博客发表时,BZOJ1607题面有误,正确题面请到洛谷2926查看)

分析:

一句话题意:给定\(n\)个数\(\{a_i\}\),求对于每个\(a_i\)有多少个数\(a_j\)满足\(a_i|a_j\) \((1\leq i,j\leq n\)且\(i \neq j)\)

按题意模拟的话\(O(n^2)\)肯定过不去。考虑对于一个数\(a_i\),它仅会对所有\(a_i*k(1 \leq k\)且\(k\)为整数) 产生1的贡献。于是可以用\(M/a_i(M=max(\{a_i\}))\)的时间给所有\(ans[a_i*k]\)加上1 (\(ans[x]\)表示有多少个\(a_i\)能整除\(x\)) ,据说这样的复杂度是\(O(n\log n)\)的

注意可能有多个\(a_i\)相等,枚举\(a_i\)可能会多次执行相同的操作,费时间。用\(cnt[x]\)记录有多少个\(i\)满足\(a[i]=x\)。枚举\(x\),每个\(x\)对\(kx\)的贡献是\(cnt[x]\)

以及一头牛不会拍自己的头,所以最终答案是\(ans[a_i]-1\)(详见代码)

代码:

#include <cstdio>
using namespace std; namespace zyt
{
const int M = 1e6 + 10, N = 1e5 + 10;
void work()
{
static int ans[M], cnt[M], arr[N];
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &arr[i]);
cnt[arr[i]]++;
}
for (int i = 1; i <= M; i++)
if (cnt[i])
for (int j = i; j <= M; j += i)
ans[j] += cnt[i];
for (int i = 1; i <= n; i++)
printf("%d\n", ans[arr[i]] - 1); }
}
int main()
{
zyt::work();
return 0;
}

最新文章

  1. C++-Qt【1】-退出程序&amp;静态调试
  2. RabbitMQ Topic exchange
  3. chrome浏览器插件的开启快捷键
  4. 使用D3绘制图表(6)--竖直柱状图表
  5. 第二章--Win32程序运行原理 (部分概念及代码讲解)
  6. EF Code First 数据库迁移Migration剖析
  7. 第二百一十一天 how can i 坚持
  8. WHAT?【 $.fn.extend() 】vs【 $.extend() 】
  9. SQL 增删改查45道题
  10. 遇到android.os等系统sdk包没有自动导入的情况
  11. Minecraft
  12. Eclipse远程调试应用程序
  13. uploadify在火狐下上传不了的解决方案,java版(Spring+SpringMVC+MyBatis)详细解决方案
  14. js实现 页面加载 完成 后顺序 执行
  15. hive删除表和表中的数据
  16. golang实现障碍、转弯最少的A*寻路
  17. java静态工厂
  18. docker相关操作
  19. luogu1856
  20. 动态库DLL中类的使用

热门文章

  1. 51nod 1241 特殊的排序
  2. WIKIOI 1319 玩具装箱
  3. nyoj 5 Binary String Matching(string)
  4. HDU 1249 三角形的分割
  5. TCP/IP协议1
  6. D. Palindromic characteristics
  7. Luca Canali
  8. phpstorm安装和调试
  9. 发现所有的字都被加上了 &lt;font&gt; 标签,导致样式全部错乱
  10. Codeforces #2B The least round way(DP)