2024暑假集训测试14

前言

image

最可惜的一点还是本来 T3 暴力能拿 \(20\),优化成 \(15\) 了,不然就 rk2 了,晚上可能又有泡面吃了。

不过因为 T2、T4 两道水题,剩下两道不太可做(至少对于我是这样的),这两题不挂分的打的貌似都不错。

T3 没学过莫反输麻了。

T1 黑暗型高松灯

本来应该是 T4,学长特意把 T1、T4 swap 了,不可做题,学长和我们说用处不大可以不用改,是什么势能函数之类的东西,听都没没听过。

T2 速度型高松灯

做过原题?赛时忘了做过当新题做的,赛后找原题才发现做过。

\(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,但昨天赛后抢到学长最优解搞到一桶泡面,就当昨天那个是今天拿的吧。

posted @ 2024-07-28 19:46  卡布叻_周深  阅读(54)  评论(0)    收藏  举报