BZOJ4546 : 三元组

设$f(x)=\sum_{x|d}p(d)$。

则$ans=\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^n\mu(i)\mu(j)\mu(k)f(lcm(i,j))f(lcm(i,k))f(lcm(j,k))$。

转化成图论模型,$i$到$j$有边的条件是$\mu(i)\neq0,\mu(j)\neq0,lcm(i,j)\leq n$。

枚举square-free的$\gcd$,再枚举square-free的$lcm$,然后枚举$\frac{lcm}{\gcd}$的因子$a$,那么可以得到一对满足条件的数对$(a\times\gcd,\frac{lcm}{a})$。

这样可以不重不漏地枚举出所有边,然后三元环计数即可。

时间复杂度$O(n\log n\sqrt{n\log n})$。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100005,M=1166760,E=760745;
int n,i,j,k,x,y,z,P[N],f[N],vis[N],mu[N],p[N],tot,ans,A,B;
int g[N],v[M],nxt[M],ed,d[N];
inline void read(int&a){char c;while(!(((c=getchar())>=‘0‘)&&(c<=‘9‘)));a=c-‘0‘;while(((c=getchar())>=‘0‘)&&(c<=‘9‘))(a*=10)+=c-‘0‘;}
inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
namespace Triple{
int g[N],v[E],w[E],nxt[E],ed,st[N],en[N],m,q[M],val[M],tmp[N];
inline void add(int x,int y,int z){
  if(d[x]>d[y])swap(x,y);
  v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;
}
void solve(){
  for(i=1;i<=n;i++)if(g[i]){
    st[i]=m+1;
    for(j=g[i];j;j=nxt[j])tmp[q[++m]=v[j]]=w[j];
    en[i]=m;
    sort(q+st[i],q+m+1);
    for(j=st[i];j<=m;j++)val[j]=tmp[q[j]];
  }
  for(i=1;i<=n;i++)for(j=g[i];j;j=nxt[j]){
    k=v[j],x=st[i],y=st[k];
    while(x<=en[i]&&y<=en[k])if(q[x]==q[y]){
      z=q[x];
      A+=mu[i]*mu[k]*mu[z]*w[j]*val[x]*val[y];
      x++,y++;
    }else q[x]<q[y]?x++:y++;
  }
}
}
int main(){
  read(n);
  for(i=1;i<=n;i++)read(P[i]);
  for(i=1;i<=n;i++)for(j=i;j<=n;j+=i)f[i]+=P[j],add(j,i);
  for(mu[1]=1,i=2;i<=n;i++){
    if(!vis[i])p[tot++]=i,mu[i]=-1;
    for(j=0;i*p[j]<=n&&j<tot;j++){
      vis[i*p[j]]=1;
      if(i%p[j])mu[i*p[j]]=-mu[i];else break;
    }
  }
  for(i=1;i<=n;i++)ans+=mu[i]*f[i]*f[i]*f[i];
  for(i=1;i<=n;i++)if(mu[i])for(j=i;j<=n;j+=i)if(mu[j]&&mu[j/i])for(k=g[j/i];k;k=nxt[k]){
    x=i*v[k],y=j/v[k];
    if(x>=y)continue;
    d[x]++,d[y]++;
    B+=(mu[x]*f[y]+mu[y]*f[x])*f[j]*f[j];
  }
  for(i=1;i<=n;i++)if(mu[i])for(j=i;j<=n;j+=i)if(mu[j]&&mu[j/i])for(k=g[j/i];k;k=nxt[k]){
    x=i*v[k],y=j/v[k];
    if(x>=y)continue;
    Triple::add(x,y,f[j]);
  }
  Triple::solve();
  return printf("%d",(ans+A*6+B*3)&((1<<30)-1)),0;
}

  

时间: 2024-11-29 13:43:12

BZOJ4546 : 三元组的相关文章

稀疏矩阵的三元组顺序表的C语言实现

对于没有排序功能的集合来说,都可以使用java.util.Collections.sort()方法进行排序,它除了集合对象以外,还需要提供一个比较器.如果列表中的元素全部都是相同的类型,并且这个类实现了Comparable接口,就可以简单的调用Collections.sort()方法,如果这个类没有实现comparable接口,那么可以创建一个比较器传递一个Comparator实例作为Sort()的第二个参数进行排序,另外,如果不想使用默认的分类顺序进行排序,同样也可以传递一个Comparato

稀疏矩阵的三元组顺序表存储及矩阵相乘算法小结

稀疏矩阵的三元组顺序表存储及矩阵相乘算法小结 巧若拙(欢迎转载,但请注明出处:http://blog.csdn.net/qiaoruozhuo) 一:稀疏矩阵的三元组顺序表数据结构 typedef int ElemType; typedef struct { intx, y;  //该非零元素的行下标和列下标 ElemTypee; //该非零元素的值 } Triple; typedef struct { Tripledata[MAXSIZE]; //非零元素三元组顺序表 intmu, nu, t

三元组的使用

#include<stdio.h>#include<stdlib.h>int InitTriplet(int **T,int v1,int v2,int v3){    *T=(int*)malloc(3*sizeof(int));    if(!*T)    {        printf("分配空间失败!\n");        exit(-1);    }    (*T)[0]=v1,(*T)[1]=v2,(*T)[2]=v3;    return 1;}

[DataStructure]稀疏矩阵的三元组存储及乘法运算

P.S.我去..我大作业不会打成系数矩阵了吧!!!!!!!!!!! 一.题目描述: 对于一个Rows X Columns稀疏矩阵,使用三元组的方法进行存储. 并在此基础上计算矩阵的乘法 二.解题报告 1.建立结构_Matrix 1 MAXVALUE为预估零元峰值个数, 2 struct _Matrix 3 { 4 int Sum;//实际输入总非零点数 5 int Rows,Columns;//矩阵行数,列数 6 double Data[MAXVALUE+1];//数据域,第i个数据的值 7 i

Project Euler 87 :Prime power triples 素数幂三元组

Prime power triples The smallest number expressible as the sum of a prime square, prime cube, and prime fourth power is 28. In fact, there are exactly four numbers below fifty that can be expressed in such a way: 28 = 22 + 23 + 2433 = 32 + 23 + 2449

数据结构之自建算法库——稀疏矩阵的三元组表示

本文针对数据结构基础系列网络课程(5):数组与广义表中第3课时稀疏矩阵的三元组表示. 稀疏矩阵的三元组表示相关的算法库采用程序的多文件组织形式,包括两个文件: 1.头文件:tup.h,包含定义稀疏矩阵的三元组表示数据结构的代码.宏定义.要实现算法的函数的声明: #ifndef TUP_H_INCLUDED #define TUP_H_INCLUDED #define M 6 #define N 7 #define MaxSize 100 //矩阵中非零元素最多个数 typedef int Ele

FZU1669 Right-angled Triangle【毕达哥拉斯三元组】

题目链接: http://acm.fzu.edu.cn/problem.php?pid=1669 题目大意: 求满足以a.b为直角边,c为斜边,并且满足a + b + c <= L的直角三角形的个数. 思路: 勾股定理,a.b.c也就是本原毕达哥拉斯三元组,则满足: x = m^2 - n^2 y = 2*m*n z = m^2 + n^2 其中m > n,且若m为奇数,则n为偶数,若m为偶数,则n为奇数. 枚举m.n,然后将三元组乘以i倍,保证 i * (x + y + z)在所给范围内(2

UvaLive 6667 Longest Chain (分治求三元组LIS&amp;树状数组)

题目链接: here 题意: 和hdu4742类似.区别就是一部分三元组是直接给出的.还有一部分是用他给的那个函数生成的.还有就是这里的大于是严格的大于a>b必须ax>bx,ay>by,az>bz. 思路: 思路也和hdu4742here类似.只是有几个比较棘手的问题.现在变成严格大于了.对于y还是很好办的.我们在排序y的时候可以使的标号大的排在前面这样就可以防止y和它一样的更新它了.感觉比较麻烦的是x一样怎么办.这个真没想出什么好办法.就只有x和mid+1的x不一样的建一个树状数

【数据结构与算法】一、三元组的代码实现

开始复习数据结构和算法,好长时间没写c了,顺便复习一下 三元组的表示与实现 #include<iostream> #include <stdlib.h> using namespace std; //函数结果状态代码 #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 //函数结果类型 typedef int Status; //数