2024暑假集訓測試14

卡布叻_周深發表於2024-07-28

前言

  • 比賽連結

image

最可惜的一點還是本來 T3 暴力能拿 \(20\),最佳化成 \(15\) 了,不然就 rk2 了,晚上可能又有泡麵吃了。

不過因為 T2、T4 兩道水題,剩下兩道不太可做(至少對於我是這樣的),這兩題不掛分的打的貌似都不錯。

T3 沒學過莫反輸麻了。

T1 黑暗型高松燈

本來應該是 T4,學長特意把 T1、T4 swap 了,不可做題,學長和我們說用處不大可以不用改,是什麼勢能函式之類的東西,聽都沒沒聽過。

T2 速度型高松燈

  • 原題:P3216 [HNOI2011] 數學作業

做過原題?賽時忘了做過當新題做的,賽後找原題才發現做過。

\(t\) 表示當前數字的位數,有 \(f_x = f_{x-1} \times 10^t + x\) ,位數一樣的矩陣快速冪,位數不同的兩個連線點特殊處理即可。

對於位數一樣的,有:

\[\begin{bmatrix} dp_i\\ i\\ 1 \end{bmatrix} = \begin{bmatrix} 10^k & 1 & 1\\ 0 & 1 & 1\\ 0 & 0 & 1 \end{bmatrix} \times \begin{bmatrix} dp_{i-1}\\ i-1\\ 1 \end{bmatrix} \]

我這個做法不開 __int128 會炸。

點選檢視程式碼
#include<bits/stdc++.h>
#define ll __int128
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=1e5+10;
template<typename Tp> inline void read(Tp&x)
{
    x=0;register bool z=true;
    register char c=getchar();
    for(;c<'0'||c>'9';c=getchar()) if(c=='-') z=0;
    for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    x=(z?x:~x+1);
}
template<typename Tp> inline void wt(Tp x)
{if(x>9)wt(x/10);putchar((x%10)+'0');}
template<typename Tp> inline void write(Tp x)
{if(x<0)putchar('-'),x=~x+1;wt(x);}
ll n,m,P,a[10][10],ans[10][10],c[10][10],last,ans1,ans2,anss;
ll qpow(ll a,ll b)
{
    ll ans=1;
    for(;b;b>>=1)
    {
        if(b&1) ans*=a;
        a*=a;
    }
    return ans;
}
void qpow(ll b)
{
    memset(ans,0,sizeof(ans));
    for(int i=1;i<=3;i++) ans[i][i]=1;
    for(;b;b>>=1)
    {
        if(b&1)
        {
            for(int i=1;i<=3;i++)
                for(int j=1;j<=3;j++)
                    for(int k=1;k<=3;k++)
                        (c[i][j]+=(ans[k][j]*a[i][k])%P)%=P;
            for(int i=1;i<=3;i++)
                for(int j=1;j<=3;j++)
                {
                    ans[i][j]=c[i][j];
                    c[i][j]=0;
                }
        }
        for(int i=1;i<=3;i++)
            for(int j=1;j<=3;j++)
                for(int k=1;k<=3;k++)
                    (c[i][j]+=(a[i][k]*a[k][j])%P)%=P;
        for(int i=1;i<=3;i++)
            for(int j=1;j<=3;j++)
            {
                a[i][j]=c[i][j];
                c[i][j]=0;
            }
    }
}
signed main()
{
    read(n),read(P);
    ll y=n;
    while(y) {m++; y/=10;}
    for(int i=1;i<=m;i++)
    {
        ll t=qpow(10,i);
        a[1][1]=t,a[2][1]=1,a[3][1]=1;
        a[1][2]=0,a[2][2]=1,a[3][2]=1;
        a[1][3]=0,a[2][3]=0,a[3][3]=1;
        ll x=t/10;
        if(i!=m) qpow(t-x-2);
        else 
        {
            if(n>x) qpow(n-x-1);
            else 
            {
                anss=((last*t)%P+x)%P;
                break;
            }
        }
        ans2=((last*t)%P+x)%P;
        ans1=((ans2*t)%P+x+1)%P;
        anss=(((ans1*ans[1][1])%P+((x+1)*ans[2][1])%P)%P+1*ans[3][1])%P;
        last=anss;
    }
    write(anss);
}

T3 力量型高松燈

  • 原題:P6156 簡單題,加強版:P6222 「P6156 簡單題」加強版

  • 部分分 \(20pts\)\(O(n^2\log n)\) 暴力,預處理可到 \(O(n^2)\)

  • 正解:

    大多數人能一眼看出莫反,到我沒學過,賽後找了篇部落格但沒認真學,就看了看到把題解看懂的地步,有時間再系統學。

    就看到了一個 \((\sum\limits_{d|n}\mu(d))=[n=1]\) 做這題有用的,剩下的都是套路。

    \[\begin{aligned} &\sum_{i=1}^n\sum_{j=1}^n(i+j)^k\mu^2(\gcd(i,j))\gcd(i,j)\\ =&\sum_{d=1}^n\mu^2(d)d\sum_{i=1}^n\sum_{j=1}^n(i+j)^k[\gcd(i,j)=d]\\ =&\sum_{d=1}^n\mu^2(d)d\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{d}\rfloor}(d(i+j))^k[\gcd(i,j)=1]\\ =&\sum_{d=1}^n\mu^2(d)d^{k+1}\sum_{i=1}^{\lfloor\frac nd\rfloor}\sum_{j=1}^{\lfloor\frac nd\rfloor}(i+j)^k[\gcd(i,j)=1]\\ =&\sum_{d=1}^n\mu^2(d)d^{k+1}\sum_{i=1}^{\lfloor\frac nd\rfloor}\sum_{j=1}^{\lfloor\frac nd\rfloor}(i+j)^k\sum_{e|i,e|j}\mu(e)\\ =&\sum_{d=1}^n\mu^2(d)d^{k+1}\sum_{i=1}^{\lfloor\frac n{de}\rfloor}\sum_{j=1}^{\lfloor\frac n{de}\rfloor}(e(i+j))^k\sum_{e|i,e|j}\mu(e)\\ =&\sum_{e=1}^n\mu(e)e^k\sum_{d=1}^{\lfloor\frac ne\rfloor}\mu^2(d)d^{k+1}\sum_{i=1}^{\lfloor\frac n{de}\rfloor}\sum_{j=1}^{\lfloor\frac n{de}\rfloor}(i+j)^k\\ =&\sum_{T=1}^nS\left(\left\lfloor\frac nT\right\rfloor\right)T^k\sum_{d|T}\mu^2(d)\mu\left(\frac Td\right)d \end{aligned} \]

    其中 \(S(n)=\sum\limits_{i=1}^n\sum\limits_{j=1}^n(i+j)^k\)

    問題來到怎麼求 \(S(n)\) 和它後面那一坨。

    先求後面那一坨,設 \(f(n)=\sum\limits_{d|T}\mu^2(d)\mu\left(\frac Td\right)d\),因為其內部均為積性函式,故 \(f(n)\) 也是積性函式,對於質數 \(p\),其次方為 \(c\)

    • \(c=1\),滿足積性。
    • \(c=2\)\(f(p^2)=\mu^2(p^2)\mu(1)p^2+\mu^2(p)\mu(p)p+\mu^2(1)\mu(p^2)\times 1=-p\)。】
    • \(c>2\),任意組合均能使 \(\mu(d),\mu(\frac Td)\) 中的一個為 \(0\),故結果一定為 \(0\)

    線性篩的時候直接處理即可。

    來看 \(S(n)\),設 \(F(n)=\sum\limits_{i=1}^ni^k\)\(G(n)=\sum\limits_{i=1}^nF(i)\),那麼有 \(S(n)=G(2n)-2G(n)\),證明比較顯然,可以手摸一下,也可以數學歸納。

    由於 \(i^k\) 也是積性函式,篩的時候直接處理即可。

    最後數論分塊處理答案即可。

    點選檢視程式碼
    #include<bits/stdc++.h>
    #define ll long long 
    #define endl '\n'
    #define sort stable_sort
    using namespace std;
    const int N=1e7+10,P=998244353;
    template<typename Tp> inline void read(Tp&x)
    {
        x=0;register bool z=true;
        register char c=getchar();
        for(;c<'0'||c>'9';c=getchar()) if(c=='-') z=0;
        for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
        x=(z?x:~x+1);
    }
    template<typename Tp> inline void wt(Tp x)
    {if(x>9)wt(x/10);putchar((x%10)+'0');}
    template<typename Tp> inline void write(Tp x)
    {if(x<0)putchar('-'),x=~x+1;wt(x);}
    ll n,k,tot,cnt,ans,prime[N],f[N],g[N];
    bool vis[N];
    ll qpow(ll a,ll b)
    {
        ll ans=1;
        for(;b;b>>=1)
        {
            if(b&1) (ans*=a)%=P;
            (a*=a)%=P;
        }
        return ans;
    }
    void sieve()
    {
        f[1]=g[1]=1;
        for(int i=2;i<=2*n;i++)
        {
            if(!vis[i])
            {
                prime[++tot]=i;
                f[i]=i-1;
                g[i]=qpow(i,k);
            }
            for(int j=1;j<=tot&&i*prime[j]<=2*n;j++)
            {
                vis[i*prime[j]]=1;
                g[i*prime[j]]=g[i]*g[prime[j]]%P;
                if(i%prime[j]==0)
                {
                    if((i/prime[j])%prime[j]!=0)
                        f[i*prime[j]]=(P-prime[j])*f[i/prime[j]]%P;
                    break;
                }
                f[i*prime[j]]=f[i]*f[prime[j]]%P;
            }
        }
        for(int i=2;i<=2*n;i++) 
        {
            f[i]=(f[i-1]+f[i]*g[i]%P)%P;
            g[i]=(g[i-1]+g[i])%P;
        }
        for(int i=2;i<=2*n;i++) g[i]=(g[i-1]+g[i])%P;
    }
    ll s(ll x)
    {
        return (g[x<<1]-2*g[x]%P+P)%P;
    }
    signed main()
    {
        read(n),read(k);
        sieve();
        for(ll l=1,r=0;l<=n;l=r+1)
        {
            r=n/(n/l);
            (ans+=s(n/l)*((f[r]-f[l-1]+P)%P)%P)%=P;
        }
        write(ans);
    }
    

T4 高松燈

看題名就知道簽到題,要麼取自己要麼第一位取次大值後面全取 \(9\),但我賽時想都沒想搞了個數位 DP 上去。

總結

沒學過的知識點還是太多,這次只掛了 \(5pts\) 而且打的不是很唐,所以好像沒啥心得,好多題逆推退不出來想想正推,反過來也是,T2 倒推半天出不來正推直接過了。

附錄

雖然今天可惜沒拿到 rk2,但昨天賽後搶到學長最優解搞到一桶泡麵,就當昨天那個是今天拿的吧。