【51nod1965】奇怪的式子

Portal --> 51nod1965

Solution

  怎么说呢。。这题。。做的有点痛苦。。

  首先看这个式子长得。。比较奇怪,指数里面那个加号有点烦人,而且这个函数不是一个积性函数也有点烦人,那就考虑把这个函数拆成两部分来算
\[
\prod\limits_{i=1}^{n}\sigma_0 (i)^{\mu (i)+i}=\prod\limits_{i=1}^{n}\sigma_0(i)^i\cdot\prod\limits_{i=1}^{n}\sigma_0(i)^{\mu (i)}
\]
  首先看第一部分的处理,我们记\(Sum(i)=\frac{n(n+1)}{2}\),那么有:
\[
\begin{aligned}
&\prod\limits_{i=1}^{n}\sigma_0(i)^i=\prod\limits_{p}\prod\limits_{k}(k+1)^W\&W=p^k\cdot Sum(\lfloor \frac{n}{p^k}\rfloor)-p^{k+1}\cdot Sum(\lfloor \frac{n}{p^k+1}\rfloor)\\end{aligned}
\]
  具体一点的话就是,因为这里是连乘,然后\(\sigma_0(x)\)是一个积性函数,所以我们考虑将每一个\(i\)分解质因数,然后按照分解的质因数把每个\(\sigma_0\)写开

  那么,枚举素数\(p\),枚举这个素数的指数\(k\),然后统计分解质因数后\(p\)的指数恰好为\(k\)的数的个数,然后算贡献就好了

  然而这个式子还是不能直接用来求解第一部分的答案,所以我们还要进一步处理

  考虑分成\(p<=\sqrt n\)和\(p>\sqrt n\)两类来看:

  首先对于\(p<=\sqrt n\)的部分,是可以直接计算而不会T掉的

  然后对于\(p>\sqrt n\)的部分,\(p\)的指数\(k\)只能是\(1\)(因为\(p>\sqrt n\)),所以:
\[
\begin{aligned}
&\prod\limits_{p>\sqrt n}\prod\limits_{k}(k+1)^W=\prod\limits_{p>\sqrt n}2^{W'}\&W'=Sum(\lfloor \frac{n}{p} \rfloor)\\end{aligned}
\]
  这个部分的话,因为\(\lfloor \frac{n}{p}\rfloor\)的取值只有\(2\sqrt n\)个,所以我们可以直接用莫比乌斯反演中的那个常用技巧,分块一下求就可以了

  然后整个过程中我们需要预先处理出来的东西有两个:约数个数和约数和

  这两个东西用min_25筛一下就好了

  然而!

  这样我们求出来的是\(2\)的指数部分,这个数在计算的过程中如果不加取模操作的话会奇大无比,这就很尴尬

  注意到题目中的模数是一个素数,那么我们可以用一下由欧拉定理得到的一个结论:
\[
x^y\equiv x^{y\ mod\ \phi(p)}(mod\ p)
\]
  也就是说我们可以对指数部分的计算\(\%\phi(p)\)(也就是\(p-1\)),并不会影响结果,问题解决ovo

  
  
  

  然后看第二部分,这一个部分看上去会比较麻烦(实际上也确实有点麻烦)

  把式子单独列出来:
\[
\prod\limits_{i=1}^{n}\sigma_0(i)^{\mu(i)}
\]
  首先来分析一下什么样的\(i\)才会被算进去

  由于\(\mu(i)\)有一个很好的性质:当\(i\)有平方因子的时候\(\mu(i)=0\),所以我们接下来对\(i\)的讨论可以多一个前提就是\(i\)分解质因数之后每一个素数的指数都是\(1\)

  那么沿用处理第一部分的时候的想法,我们将每个\(i\)分解质因数拆开来写

  用\(d(i)\)表示\(i\)的质因数个数,那么可以得到:
\[
\prod\limits_{i=1}^{n}\sigma_0(i)^{\mu(i)}=\prod\limits_{i=1}^{n}2^{d(i)\cdot\mu(i)}
\]
  有了上面的欧拉定理得到的结论支撑,我们就可以放心大胆地先求指数再求结果啦

  用类似min_25筛中设状态的方式:

  记\(minp(i)\)表示\(i\)的最小质因子,\(d(i)\)表示\(i\)的质因数个数,\(P\)为素数列表

  首先大力定义
\[
f(i,j)=\sum\limits_{k=1}^{i}[i\in Prime或minp(i)>P_j]\mu(i)\cdot d(i)
\]
  然后为了方便转移我们还需要定义一个辅助数组
\[
f1(i,j)=\sum\limits_{k=1}^{i}[i\in Prime或minp(i)>P_j]\mu(i)
\]
  那么我们可以得到转移:
\[
\begin{aligned}
&f1(i,j)=f1(i,j+1)+(-1)*(f1(\lfloor \frac{n}{P_j}\rfloor,j+1)-f1(P_j,j+1))\&f(i,j)=f(i,j+1)+(-1)*(f(\lfloor \frac{n}{P_j}\rfloor,j+1)-f(P_j,j+1))+(-1)*(f1(\lfloor \frac{n}{P_j}\rfloor,j+1)-f1(P_j,j+1))
\end{aligned}
\]
  初始化\(f1(i,max)=f(i,max)=(-1)*[1,i]范围内素数个数\),\(max\)表示的是\(>=\sqrt n\)的第一个素数在列表中的下标

  具体一点的话就是,首先所有的\((-1)\)其实都是\(\mu (p)\)的值,因为是素数的\(\mu\)值所以是\(-1\)

  然后转移的话其实就是要加上\(范围内的[1,i]范围内的minp(x)=P_j\)的数的贡献,为了保证有\(P_j\)的存在并且是最小的,所以调用的是\(f(\lfloor\frac{n}{P_j}\rfloor,j+1)\)和\(f1(\lfloor\frac{n}{P_j}\rfloor,j+1)\),然后还要保证素数不会被多算一次所以要去掉素数部分也就是\(f(P_j,j+1)\)和\(f1(P_j,j+1)\)

  然后就可以快乐dp得出答案啦

?  

  一些实现的细节问题:

    1.这题的模数比较巨大,两个数的乘积可能爆long long,所以要。。用一个奇妙黑科技,也就是用long double 模拟取模这样来取模qwq

    2.注意在算的过程中的模数到底是用\(\phi(MOD)\)还是\(MOD\)要看清楚。。调了好久。。

    3.在求的过程中因为数字都比较巨大所以。。要积极取模

(调试调到后来直接放弃思考见到乘号就取模导致代码长得十分不可描述并且常数巨大qwq)

?   

  代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define ld long double
using namespace std;
const int MAXN=1e6+10;
const ll MOD=1e12+39,PHIMOD=MOD-1;
ll pcnt[MAXN*2],psum[MAXN*2],g[MAXN*2],f[MAXN*2],f1[MAXN*2];
ll P[MAXN],rec[MAXN*2];
int loc1[MAXN],loc2[MAXN];
bool vis[MAXN];
ll n,m,sq,cnt,cntval,ans,T;
void prework(int n);
void init_loc();
void get_g();
int Pos(ll x){return x<=sq?loc1[x]:loc2[n/x];}
ll Sum(ll l,ll r);
ll ksm(ll x,ll y);
ll mul(ll x,ll y,ll mod){
    ld tmp=(ld)x*(ld)y;
    return (x*y-((ll)(tmp/(ld)mod)*mod)+mod)%mod;
}
void solve1();
void solve2();

int main(){
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
#endif
    scanf("%d",&T);
    prework(MAXN);
    for (int o=1;o<=T;++o){
        scanf("%lld",&n);
        sq=sqrt(n)+0.5;
        m=upper_bound(P+1,P+1+cnt,sq)-P-1;
        init_loc();
        get_g();
        ans=1;
        solve1();
        solve2();
        printf("%lld\n",ans);
    }
}

void prework(int n){
    cnt=0;
    for (int i=2;i<=n;++i){
        if (!vis[i])
            P[++cnt]=i;
        for (int j=1;j<=cnt&&P[j]*i<=n;++j){
            vis[i*P[j]]=true;
            if (i%P[j]==0) break;
        }
    }
}

void init_loc(){
    cntval=0;
    for (ll i=1,pos;i<=n;i=pos+1){
        rec[++cntval]=n/i;
        pos=n/(n/i);
    }
    reverse(rec+1,rec+1+cntval);
    for (int i=1;i<=cntval;++i)
        if (rec[i]<=sq) loc1[rec[i]]=i;
        else loc2[n/rec[i]]=i;
}

void get_g(){
    for (int i=1;i<=cntval;++i)
        pcnt[i]=rec[i]-1,psum[i]=Sum(1,rec[i])-1;
    for (int j=1;j<=m;++j)
        for (int i=cntval;i>=1&&rec[i]>=1LL*P[j]*P[j];--i){
            pcnt[i]-=pcnt[Pos(rec[i]/P[j])]-pcnt[Pos(P[j]-1)];
            psum[i]=(psum[i]+PHIMOD-P[j]*(psum[Pos(rec[i]/P[j])]+PHIMOD-psum[Pos(P[j]-1)])%PHIMOD)%PHIMOD;
        }
}

ll Sum(ll l,ll r){
    ll tmp=l+r,tmp1=r-l+1;
    if (tmp&1) tmp1/=2;
    else tmp/=2;
    return mul(tmp,tmp1,PHIMOD);
}

ll ksm(ll x,ll y){
    ll ret=1,base=x;
    for (;y;y>>=1,base=mul(base,base,MOD))
        if (y&1) ret=mul(ret,base,MOD);
    return ret;
}

void solve1(){//\prod \sigma i^i
    ll tmp;
    for (int i=1;i<=m;++i){
        tmp=P[i];
        for (int k=1;tmp<=n;tmp*=P[i],++k)
            ans=mul(ans,ksm(k+1,(tmp*Sum(1,n/tmp)%PHIMOD-tmp*P[i]%PHIMOD*Sum(1,n/(tmp*P[i]))%PHIMOD)+PHIMOD)%PHIMOD,MOD);
    }
    tmp=0;
    for (int i=Pos(sq)+1;i<=cntval;++i)
        tmp+=mul(Sum(1,n/rec[i]),(psum[i]-psum[i-1]+PHIMOD)%PHIMOD,PHIMOD);
    ans=mul(ans,ksm(2,tmp),MOD);
}

void solve2(){//\prod \sigma i^{\mu i}
    for (int i=2;i<=cntval;++i) f1[i]=f[i]=PHIMOD-pcnt[i];
    for (int j=m;j>=1;--j){
        for (int i=cntval;i>=2&&rec[i]>=P[j]*P[j];--i){
            f1[i]=(f1[i]+(-1LL)*(f1[Pos(rec[i]/P[j])]-f1[Pos(P[j])]))%PHIMOD;
            f[i]=(f[i]+(-1LL)*(f[Pos(rec[i]/P[j])]-f[Pos(P[j])])+(-1LL)*(f1[Pos(rec[i]/P[j])]-f1[Pos(P[j])]))%PHIMOD;
            if (f1[i]<0) f1[i]+=PHIMOD;
            if (f[i]<0) f[i]+=PHIMOD;
        }
    }
    ans=mul(ans,ksm(2,f[Pos(n)]),MOD);
}

原文地址:https://www.cnblogs.com/yoyoball/p/9196092.html

时间: 2024-10-04 13:34:14

【51nod1965】奇怪的式子的相关文章

[51nod1965]奇怪的式子(Min_25筛)

题面 传送门 题解 好毒啊--\(de\)了一个晚上的\(bug\)-- 题目所求为 \[\prod_{i=1}^n\sigma_0(i)^{\mu(i)+i}(mod\ 10^{12}+39)\] 那么我们把式子拆开来,变成 \[(\prod_{i=1}^n\sigma_0(i)^{\mu(i)})(\prod_{i=1}^n\sigma_0(i)^i)\] 左边 现在就是要求\(\prod_{i=1}^n\sigma_0(i)^{\mu(i)}\) 我们发现只有在所有质因子都不超过\(1\)

[51nod1965]奇怪的式子

description 求\[\prod_{i=1}^n\sigma_0(i)^{\mu(i)+i}(mod\ 10^{12}+39)\]其中\(\sigma_0(i)\)表示约数个数. solution 菜鸡fdf现在才学\(Min\_25\)筛. 拆幂即转化为\((\prod_{i=1}^n\sigma_0(i)^{\mu(i)})(\prod_{i=1}^n\sigma_0(i)^i)\). Part 1 求\[\prod_{i=1}^n\sigma_0(i)^{\mu(i)}\] 唔[托

gym 101858

我这个傻逼被治了一下午. 大好的橘势,两个小时6T,去看L,哇傻逼题.然后我跑的最短路T到自闭 最后十几分钟去想了下A,一直在想如何表示状态..就是想不到二进制搞一下... 然后游戏结束了..以后我就是蓝名之耻了.(注:此称号送给一场比赛里排名最低的蓝名选手) 所以非常凄惨到现在也只有8个,,我还想AK来着,,毕竟有紫名选手AK了,那我1800多分也差不多叭 注意:堆优化dijkstra的复杂度是mlogm!!! 注意:堆优化dijkstra的复杂度是mlogm!!! 注意:堆优化dijkstr

模拟82 题解

A. D2T1 因为最终答案只需要大小为$n$的排列的返回值的期望. 我们并不关注排列内部的内容. 所以不妨设长度为$n$的排列的返回值的期望为$f_n$,长度为$n$的排列的逆序对个数为$g_n$. 那么有$f_n=\frac{\sum \limits_{i=0}^{n}\binom{n}{i}*f_i}{2^n}+g_n$. 显然随机排列中正序对和逆序对个数应当是相同的,并且二者相加为$\frac{n*(n-1)}{2}$,故$g_n=\frac{n*(n-1)}{4}$. 然而受到$D1T

修改 const 的值之后的奇怪变化

1 #include <iostream> 2 3 int main(void) 4 { 5 const int a = 10; 6 int* p = (int*)&a; 7 *p = 20; 8 std::cout << a << "|" << &a << std::endl; 9 std::cout << *p << "|" << p <<

第7题:奇怪的国家&amp;第8题:字符串长度

第7题:奇怪的国家 有一个奇怪的国家,里面的国民对于事情的态度永远只有两面.当两个人遇到一起讨论一个事情的时候--两个持赞同观点的人遇到一起后会对这个事情都继续赞同:一个持赞同观点的人遇到一个持不赞同观点的人的时候,两人都会不再继续赞同:两个持不赞同观点的人遇到一起讨论后反而会对这个事情开始赞同. 输入包括两行,每行包括N个数字(1≤N≤50),分别表示两个人对于N个事情对应的看法--0表示不赞同.1表示赞同. 输出包括一行,包括N个数字,表示两人相遇后,对于这N件事情的最终看法. 样例输入 1

洛谷 P2759 奇怪的函数

P2759 奇怪的函数 题目描述 使得 x^x 达到或超过 n 位数字的最小正整数 x 是多少? 输入输出格式 输入格式: 一个正整数 n 输出格式: 使得 x^x 达到 n 位数字的最小正整数 x 输入输出样例 输入样例#1: 11 输出样例#1: 10 说明 n<=2000000000 思路:根据换底公式 可以推得,当x*log10(x)==n-1时x^x恰好为n位数,所以二分查找即可,在特判一下为1的情况. #include<cmath> #include<cstdio>

做一个手机端页面时,遇到了一个奇怪的问题:字体的显示大小,与在CSS中指定的大小不一致

最近在做一个手机端页面时,遇到了一个奇怪的问题:字体的显示大小,与在CSS中指定的大小不一致.大家可以查看这个Demo(记得打开Chrome DevTools). 就如上图所示,你可以发现,原本指定的字体大小是24px,但是最终计算出来的却是53px,看到这诡异的结果,我心中暗骂一句:这什么鬼! 随后开始对问题各种排查:某个标签引起的?某个CSS引起的?又或者是某句JS代码引起的.通过一坨坨的删代码,发现貌似都不是.我不禁又骂,到底什么鬼!不过中间还是发现了一些端倪:当页面中的标签数量或者文本数

[jzoj]1383.奇怪的问题

Link https://jzoj.net/senior/#main/show/1383 Problem Alice总是会提出很多奇怪的问题,一天他让他的朋友Bob跟他一起研究一个奇怪的问题.问题是:[A,B]中有多少个数满足组成这个数的数字之和为S,另一个问题是[A,B]内满足这一要求最小的数是哪个? 编程帮Bob解决这个问题. Solution 30分 显然可以使用暴力枚举,像我这样的渣渣,考试的时候想到数位DP,设完一个不完整的状态,根本不知道如何统计答案 100分 聪明的人都知道,若要求