hdu6706 huntian oy 杜教篩


2019CCPC網絡賽的一道題目,現場猜到了結論,但本人過於沙雕,試了一下猜想,居然不對,就立刻轉身了。

猜想是正確的,是我驗證錯了....

猜想:

\[gcd(i^a-j^a,i^b-j^b)=i-j \]

推導結果:

\[\sum_{d=1}^{N}\mu(d)\cdot d\sum_{i=1}^{\lfloor\frac{N}{d}\rfloor}\sum_{j=1}^{i}(i-j) \]

\(\lfloor\frac{N}{d}\rfloor=k\),經過推導發現

\[\sum_{i=1}^{k}\sum_{j=1}^{i}(i-j)=\frac{k^3-k}{6} \]

然后,就只剩下左邊的 \(\mu(d)\cdot d\)

\(f(d)=\mu(d)*d\) 和恆等函數 \(Id(n)=n\) 狄利克雷卷積之后得到

\[\begin{align*} (\mu(d)\cdot d)*Id(d) & = \sum_{d|n}(\mu(d)\cdot d)\cdot Id(\frac{n}{d})\\ & = \sum_{d|n}\mu(d) = [n=1] \end{align*} \]

接下來套杜教篩的公式

\[g(1)S(n)=\sum\limits_{i=1}^n(f*g)(i)-\sum\limits_{i=2}^ng(i)S(\lfloor\dfrac{n}{i}\rfloor) \]

\[\begin{align*} S(n) & = \sum\limits_{i=1}^n [i=1]-\sum\limits_{i=2}^ni\cdot S(\lfloor\dfrac{n}{i}\rfloor)\\ & = 1-\sum\limits_{i=2}^ni\cdot S(\lfloor\dfrac{n}{i}\rfloor) \end{align*} \]

至此,本題的數學分析過程已經結束,下面是我的AC代碼

#include <iostream>
#include <cstring>
#include <cstdio>
#include<unordered_map>
#define ll long long
#define INF 0x3f3f3f3f
#define MAXN 6000100
using namespace std;
unordered_map<long long,long long>w1;
const int mod = 1e9+7;
const int inv6 = 166666668;

int getSum(ll k)
{
    ll k3 = ((k*k%mod)*k)%mod;
    ll res = (k3-k+mod)%mod;
    res = res*inv6%mod;
    return res;
}
int sum[MAXN];
bool vis[MAXN];
int prime[MAXN], mu[MAXN];
void getMobius()
{
    int cnt = 0;
    mu[1] = sum[1] = 1;
    for (int i = 2; i < MAXN; i++)
    {
        if (!vis[i])
        {
            prime[cnt++] = i;
            mu[i] = -1;
        }
        sum[i] = (sum[i-1]+mu[i]*i%mod+mod)%mod;
        for (int j = 0; j < cnt; j++ )
        {
            int k = i*prime[j];
            if(k > MAXN)   break;
            vis[k] = true;
            if (i % prime[j] == 0)
            {
                break;
            }
            mu[k] = -mu[i];
        }
    }
}
unordered_map<int,long long>w;
ll djs(int x)
{
    if(x<MAXN)return sum[x];
    if(w[x])return w[x];
    ll ans=1,td,temp;
    for(int l=2,r;l>=0&&l<=x;l=r+1)
    {
        r=x/(x/l);
        td=(r-l+1);
        td = ((r+l)*td)/2;
        td%=mod;
        temp = td*djs(x/l)%mod;
        ans = (ans-temp+mod)%mod;
    }
    return w[x]=ans;
}
int main()
{
    getMobius();
    int caseN; scanf("%d", &caseN);
    while(caseN--)
    {
        int N, a, b; scanf("%d%d%d", &N, &a, &b);
        ll td, ink, res=0;
        for(int lef = 1, rig; lef <= N; lef=rig+1)
        {
            ink = N/lef;
            rig = N/ink;
            td = (djs(rig)-djs(lef-1)+mod)%mod;
            res = (res+getSum(ink)*td%mod)%mod;
        }
        printf("%lld\n", res);
    }
    return 0;
}

感想

知道我的猜想是正確的之后,吃完晚飯就開始做這道題,好久好久終於改好了

期間,簡單打表會RE,所以就轉了杜教篩

開始打表空間用的太多MLE,太少TLE

最后找到一個合適的大小6e6,不會MLE也不會TLE,結果WA了

想了一會兒,又瞄了一眼答案,好像我搞了半天的東西不太對哦

其實,只是推導結果不一樣而已

頓生絕望,算了,老子明天再看,這種套模板的題能有多難?

早上睡不着,突然想到這道題目打表范圍開大以后應該要mod的

一開始我只開了1e6,沒有mod

於是改了一下,居然AC了!哇,第一道杜教篩題目,歡天喜地!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM