[JZOJ5134][SDOI省队集训2017]三元组
来源:互联网 发布:淘宝商品主图素材 编辑:程序博客网 时间:2024/05/21 20:27
题目大意
求
推式子
首先假设a<=b<=c。
第一步转化为
注意到
所以转化为
交换一下枚举顺序
后面可以直接计算。
我们可以直接枚举i,然后考虑计算。
这个形式其实和一道叫循环之美的题差不多哦!
首先观察后两维可以分块。
于是我们需要计算一个和k互质的<=n的i的莫比乌斯函数和或者个数。
计算这个即可。
容易想到洲阁筛。
设S(i,r)表示<=r的与k的前i个质因子互质的莫比乌斯函数和。
注意因为莫比乌斯函数要不含平方因子,所以后面那个第一维仍然是i,即要求它只有一个pi。
设T(i,r)表示<=r的与与k的前i个质因子互质的数的个数。
这样递归加记忆化有点慢。
我们考虑处理g[i]表示将i每个质因子的次数改成1的数。
一个优化是一开始枚举i的时候相同g的可以利用之前的答案。
于是我们只需要计算莫比乌斯函数不为0的i。
然后设f[i]表示i的最大质因数。
我们把S的意义改为<=r的与i互质的莫比乌斯函数和,T同理。
这样的好处是可以全局记忆化。
注意到状态只有n^1.5,可以开数组存。
为什么n^1.5?因为只有分块边界会进去,而不断除以一个质数的过程可以看做常数级别。
递归会比较慢,可以改为递推的形式提前计算。
详见代码。
#include<cstdio>#include<algorithm>#include<cmath>#include<map>#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)using namespace std;typedef long long ll;const int maxn=50000+10,maxnn=700+10,mo=1000000007;int pri[maxn],mu[maxn],sum[maxn],f[maxn],g[maxn],num[maxn],p[maxn];int S[maxnn][maxn],T[maxnn][maxn],id[maxn],di[maxn];bool bz[maxn],pd[maxn],dp[maxn];int i,j,k,l,r,t,n,m,tot,pot,top,cnt,ans,a,b,c;void work(int k){ int i,j,t,l,r,sum=0; k=g[k]; if (num[k]){ (ans+=num[k])%=mo; //if (ans>=mo) ans-=mo; return; } i=1;t=0; while (i<=b){ j=min(b/(b/i),c/(c/i)); l=S[id[j]][k]; r=(ll)T[di[b/i]][k]*T[di[c/i]][k]%mo; (sum+=(ll)(l-t)*r%mo)%=mo; //if (sum>=mo) sum-=mo; t=l; i=j+1; } (ans+=sum)%=mo; //if (ans>=mo) ans-=mo; num[k]=sum;}int main(){ freopen("triple.in","r",stdin);freopen("triple.out","w",stdout); mu[1]=g[1]=1; fo(i,2,maxn-10){ if (!bz[i]){ pri[++top]=i; f[i]=g[i]=i; mu[i]=-1; } fo(j,1,top){ if ((ll)i*pri[j]>maxn-10) break; bz[i*pri[j]]=1; f[i*pri[j]]=f[i]; if (i%pri[j]==0){ g[i*pri[j]]=g[i]; break; } g[i*pri[j]]=g[i]*pri[j]; mu[i*pri[j]]=-mu[i]; } } fo(i,1,maxn-10) sum[i]=sum[i-1]+mu[i]; scanf("%d%d%d",&a,&b,&c); if (a>b) swap(a,b); if (b>c) swap(b,c); if (a>b) swap(a,b); i=1; while (i<=b){ j=min(b/(b/i),c/(c/i)); pd[j]=1; dp[b/i]=1;dp[c/i]=1; i=j+1; } fo(i,1,c) if (i==g[i]) p[++cnt]=i; fd(i,c,1){ if (pd[i]){ fo(j,1,top){ if (i<pri[j]) break; pd[i/pri[j]]=1; } } if (dp[i]){ fo(j,1,top){ if (i<pri[j]) break; pd[i/pri[j]]=1; } } } fo(i,1,c) if (pd[i]){ id[i]=++tot; if (i==1){ fo(j,1,cnt) S[tot][p[j]]=1; continue; } S[tot][1]=sum[i]; fo(j,2,cnt){ k=p[j]; S[tot][k]=(S[tot][k/f[k]]-mu[f[k]]*S[id[i/f[k]]][k])%mo; } } fo(i,1,c) if (dp[i]){ di[i]=++pot; if (i==1){ fo(j,1,cnt) T[pot][p[j]]=1; continue; } T[pot][1]=i; fo(j,2,cnt){ k=p[j]; T[pot][k]=(T[pot][k/f[k]]-T[di[i/f[k]]][k/f[k]])%mo; } } fo(i,1,a) work(i); (ans+=mo)%=mo; printf("%d\n",ans);}
- [JZOJ5134][SDOI省队集训2017]三元组
- [bzoj4927][SDOI省队集训2017]diyiti
- [bzoj4928][SDOI省队集训2017]dierti
- [bzoj4930][SDOI省队集训2017]棋盘
- [bzoj4931][SDOI省队集训2017]塔
- [JZOJ5129][SDOI省队集训2017]字符串
- [JZOJ5133][SDOI省队集训2017]重建
- [JZOJ5136][SDOI省队集训2017]重排
- [JZOJ5131][SDOI省队集训2017]距离
- [JZOJ5130][51nod1446][SDOI省队集训2017]苹果树
- [JZOJ5132][SDOI省队集训2017]子序列
- [JZOJ5135][SDOI省队集训2017]逆序对
- [JZOJ5137][SDOI省队集训2017][bzoj4842]养猫
- [JZOJ5134]三元组/[SPOJ PCOPTRIP]Counting Pairwise Coprime Triples
- 【SDOI省队集训题】棋盘(最小费用流)
- 【SDOI省队集训题】pair(线段树+二分)
- JZOJ 5432. 【NOIP2017提高A组集训10.28】三元组
- 【JZOJ 5432】【NOIP2017提高A组集训10.28】三元组
- 一些 快速 有用的 函数
- SCI 写作总结
- Leetcode-Generate Parentheses(递归)
- Cloud Control 12c Installation 错误处理 Checking swap space: 0 MB available, 150 MB required. Failed
- PAT 甲级 1017. Queueing at Bank
- [JZOJ5134][SDOI省队集训2017]三元组
- web性能
- 一个简单的公私钥加密算法
- Houdini学习 —— 使用音频驱动几何体变换之信号处理
- 结构型模式之装饰模式实现
- Xbanner
- 如何学习JAVASE
- 《JAVA与模式》之策略模式
- BZOJ 4569 [Scoi2016] 萌萌哒