📌  相关文章
📜  可以被X整除的最大K位数字的C++程序(1)

📅  最后修改于: 2023-12-03 15:22:56.557000             🧑  作者: Mango

可以被X整除的最大K位数字的C++程序

本程序用于求解由K个数字组成的数中最大的可以被X整除的数字。代码采用C++语言实现,其核心算法为“康托展开”和“数位DP”。

康托展开

康托展开是一种将一个全排列的序数转换成一个整数的方法。对于一个由n个不同元素组成的排列,它的康托展开式为:

$$X=\sum_{i=1}^{n} (a_i-1)!\times\lbrace j|j<i,a_j>a_i\rbrace$$

其中,$a_i$表示排列中第i个数字的大小,$\lbrace j|j<i,a_j>a_i\rbrace$表示排列中第i个数字前比它大的数字的个数,即逆序对的个数。

为了方便使用康托展开,我们需要将题目中要求的数转换成一个排列,其中不同的数字排列按从大到小的顺序排列。

数位DP

数位DP是一种用于处理数字排列的动态规划方法。我们可以以“选或不选某个数字”来设计状态转移,具体实现过程如下:

  1. 设计状态:通常将该问题的解设计为一个数值型的状态,表示在当前已经处理的位置上,它能够符合题目要求的最好的方案。
  2. 状态转移方程:我们考虑对于当前处理的数字$i$,它要么被选中,即使总和模$X$等于余数$R_i$,将会得到一个符合要求的解;要么不选$i$,我们需要保留下前面所得到的状态信息,以便在后面的状态转移中使用。
  3. 边界处理:我们需要保证状态转移的正确性,我们通常对该问题的一些细节进行特殊处理,比如初始状态、边界情况等等。

在本程序中,我们需要设计状态来表示当前的排列能够被$X$整除的最大数。具体使用方法请看代码。

代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

typedef long long ll;
const int maxn=15;
int n,k,R,len=0;
int dig[maxn],cnt[maxn][maxn];
ll ans=-1;

inline ll QuickPow(ll a,ll b,ll mod){
    ll ret=1;
    while(b){
        if(b&1) ret=(ret*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return ret;
}

inline void init(){
    scanf("%d%d%d",&n,&k,&R);
    while(k) dig[++len]=k%10,k/=10;
    // 倒序排列位数
    // 如:k=123456789, dig[]={9,8,7,6,5,4,3,2,1}
}

inline void dfs(int step,int num,int r,ll w){
    if(step==len+1){
        // 添加前导0
        for(int i=n-len;i>=1;i--) num=num*10;
        if(num==0) ans=max(ans,w);
        else{
            int cnt2=0;
            for(int i=1;i<=n;i++){
                int t=num%10;
                for(int j=t+1;j<=n;j++) cnt2+=cnt[R][j]-cnt[R][t];
                num/=10;
            }
            if(cnt2!=num) ans=max(ans,w);
        }
        return;
    }
    int maxx=n;
    if(step==1) maxx=dig[step];
    for(int i=maxx;i>0;i--){
        if(r<i) continue;
        dfs(step+1,num*10+i,(r-i)%R,(w+i*QuickPow(10,len-step))%R);
    }
}

inline void solve(){
    dfs(1,0,0,0);
    printf("%lld\n",ans);
} 

int main(){
    init();
    solve();
    return 0;
}
Markdown代码片段

代码片段如下:

```cpp
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

// 添加其他内容

int main(){
    // 添加主要代码
    return 0;
}