boxmoe_header_banner_img

欢迎来到DRheEheAM的blog

加载中

文章导读

Week5 Day1 | Aug. 18th


avatar
DRheEheAM_Gary 2025年8月18日 34

S+数论,高斯消元,线性基

A. B进制数与B-1倍数查询问题

我们可以通过十进制下 $\text{mod } 9$ 的结论,猜想:在 $b$ 进制下的数 $x$:$x \equiv S(x) (\text{mod } b-1)$,其中 $S(x)$ 表示 $x$ 在 $b$ 进制下所有数位总和。
接下来我们证明,设 $x$ 在 $b$ 进制下有唯一拆分:$x=x_p\times b^p+x_{p-1}\times b^{p-1}+…+x_1\times b+x_0$,且 $p=\lceil \log_{10} x\rceil $,且$ \forall 0\le i \le p \to 0\le x_i \le b-1$
则 $\forall 0\le i \le p$ ,可以发现,$ (b-1) | (b^i-1) $ .
所以,我们可以得到:
$$
\begin{aligned}
x &=x_p\times b^p+x_{p-1}\times b^{p-1}+…+x_1\times b+x_0 \\
&=(b^p-1)x_p+(b^{p-1}-1)x_{p-1}+…+(b-1)x_1+x_p+x_{p-1}+…+x_1+x_0
\end{aligned}
$$
又因为,$ (b-1) | [(b^p-1)x_p+(b^{p-1}-1)x_{p-1}+…+(b-1)x_1] $;
所以得到:
$$
x \equiv x_p+x_{p-1}+…+x_1+x_0 (\text{mod } b-1)
$$

剩下的很简单了,因为题目中给出了 $a_i \ge 1$ ,所以直接将 $S(x) \text{mod } (b-1)$ 这个数的数字减一,二分查找答案即可。

#include<bits/stdc++.h>
using namespace std;
#define intc const int
#define int long long
#define Cios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
intc N=1e6+10;
int b,q,sum,a[N];
signed main() {
    Cios;
    cin>>b>>q;
    for (int i=0;i<b;i++) {
        cin>>a[i];
        sum+=a[i]*i;
    }
    if (sum
    for (int i=1;i<b;i++) a[i]+=a[i-1];
    while (q--) {
        int k;
        cin>>k;
        if (k>=a[b-1]) cout<<-1<<endl;
        else cout<<upper_bound(a,a+b,k)-a<<endl;
    }
    return 0;
}
C++

B. 放入糖果

考虑构建抽屉。抽屉为 $0,1,2,⋯,n−1$,一共 $n$个抽屉。
根据抽屉原理,前 $n+1$ 次肯定会出现重复的抽屉被选中,并且当重复时,将形成一个周期,所以可以得出时间复杂度 $O(\text{min}(n,k))$ 。

#include<bits/stdc++.h>
using namespace std;
#define intc const int
#define int long long
#define Cios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
intc N=1e6+10;
int n,k,a[N],dfn[N],sums[N];
signed main() {
    Cios;
    cin>>n>>k;
    for (int i=0;i<n;i++) cin>>a[i];
    int flag=1,nw=0,lst=0,sum=0;
    while (k>0) {
        //cout<<sum<<endl;
        if (flag&dfn[nw]) {
            flag=0;
            int sumk=sums[dfn[lst]]-sums[dfn[nw]-1];
            sumk*=k/(dfn[lst]-dfn[nw]+1);
            sum+=sumk;
            k
            if (k<=0) break;
            // for (int i=0;i<n;i++) cout<<dfn[i]<<" ";
        }
        dfn[nw]=dfn[lst]+1;
        sum+=a[nw];
        sums[dfn[nw]]=sums[dfn[lst]]+a[nw];
        lst=nw;
        nw=sum
        k--;
    }
    cout<<sum<<endl;
    return 0;
}
C++

E. 密码箱

根据题目,我们可以很容易得出,我们要求一个数 $x\in \mathbb N$ 且 $x \le n$,使得 $x^2 \equiv 1 (\text{mod } n)$。
所以我们可以设 $x^2 = nk+1 $,其中 $k\in \mathbb N$
之后得出:
$$
\begin{aligned}
x^2 &= nk+1 \\
x^2-1 &= nk \\
(x+1)(x-1) &=nk \\
\end{aligned}
$$
所以我们得到:$n | (x+1)(x-1)$。
之后,找到 $a\in \mathbb N , b\in \mathbb N$,使得 $ab=n$ 且 $a|(n+1) \land b|(n-1)$ 或 $a|(n-1) \land b|(n-1)$。
所以我们只要在 $0\le a \le \lfloor \sqrt{n} \rfloor$ 范围内枚举 $a$ 即可。
注意,无解时,当且仅当 $n=1$。

#include<bits/stdc++.h>
using namespace std;
#define intc const int
#define int long long
#define Cios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
int n;
vector<int> x;
signed main() {
    Cios;
    cin>>n;
    if (n==1) {
        cout<<"None"<<endl;
        return 0;
    }
    cout<<"1\n";
    for (int i=1;i*i<=n;i++) {
        if (n
            int a=i,b=n/a;
            for (int j=b+1;j<=n;j+=b) {
                if ((j+1)
            }
            for (int j=b-1;j<=n;j+=b) {
                if ((j-1)
            }
        }
    }
    sort(x.begin(),x.end());
    int nn=unique(x.begin(),x.end())-x.begin()-1;
    for (int i=0;i<=nn;i++) cout<<x[i]<<endl;
    return 0;
}
C++


评论(0)

查看评论列表

暂无评论


发表评论

表情 颜文字
插入代码
DRheEheAM Blog

返回

您的消息已发送

需要反馈文章问题?点击这里...

警告
警告
警告
警告

隐私政策...

请给出具有实用,建设性的建议!
注意:若频繁发送邮件,或发送过多无意义邮件,可能会遭到临时封禁,严重者永久封禁!

警告。