首页 > 其他分享 >CF-55-D-数位DP

CF-55-D-数位DP

时间:2024-01-23 21:44:41浏览次数:32  
标签:2520 55 ll CF pos int num lcm DP

55-D 题目大意

给定区间\([l,r]\),问区间中有多少个数\(x\)满足:对于它的每一个非\(0\)位上的数\(y\),都有\(y|x\)。


Solution

经典的数位DP题型。

记录状态:\(f[pos][num][lcm]\)表示填完前\(pos\)位上的数,这些数构成了数\(num\),各个非\(0\)位数字的最小公倍数为\(lcm\),如果数\(lcm|num\),那么\(num\)也就能整除各个非\(0\)位上的数。

考虑\(num\)和\(lcm\)的上界,\(1,2···9\)的最小公倍数为\(2520\),则在记忆化搜索的过程中\(num\)不断对\(2520\)取模即可。另一方面,\(2520\)的因子数量不超过\(50\)个,也就是\(lcm\)的种类不超过\(50\)个,对这些\(lcm\)做一次映射即可。

剩下的就是套个数位DP的壳即可,因为存在多组测试数据,对于前\(pos\)位如果都已经达到了上限的话不用记忆化在\(f\)中。记忆化的话会导致下组测试数据使用到不合法的状态。

时间复杂度为\(O(2520+10·50·2520·logU+TlogU)\),实际根本无法跑满。

#include<bits/stdc++.h>
using namespace std;
using ll=long long;

ll f[20][2600][50];
int id[2600],idx=0;

void solve(){
    ll l,r;
    cin>>l>>r;
    l--;
    string x=to_string(l),y=to_string(r);
    function<ll(int,int,int,int,string&)> dp=[&](int pos,int num,int full,int lcm,string &s)->ll{
        if(pos<0){
            return num%lcm==0;
        }
        if(pos>=s.size()){
            return dp(pos-1,num,full,lcm,s);
        }
        if(!full&&f[pos][num][id[lcm]]!=-1){
            return f[pos][num][id[lcm]];
        }
        ll res=0;
        for(int i=0;i<=9;i++){
            if(full&&i>s[pos]-'0') break;
            int nxtfull=full&&(i==s[pos]-'0');
            int nxtlcm=lcm;
            if(i) nxtlcm=lcm*i/__gcd(lcm,i);
            int nxtnum=(num*10+i)%2520;
            res+=dp(pos-1,nxtnum,nxtfull,nxtlcm,s);
        }
        if(!full){
            f[pos][num][id[lcm]]=res;
        }
        return res;
    };
    reverse(x.begin(),x.end());
    reverse(y.begin(),y.end());
    ll high=dp(19,0,1,1,y);
    ll low=dp(19,0,1,1,x);
    cout<<high-low<<'\n';
}

int main(){
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    for(int i=1;i<=2520;i++){
        if(2520%i==0){
            id[i]=idx++;
        }
    }
    memset(f,-1,sizeof f);
    int T=1;
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

标签:2520,55,ll,CF,pos,int,num,lcm,DP
From: https://www.cnblogs.com/fengxue-K/p/17983477

相关文章

  • Python UDP协议发送指定格式报文
      importstructimporttimeimportsocketimportthreading#udp发送数据defsend_data(udp_socket,target_ip,target_port,send_msg):try:udp_socket.sendto(send_msg,(target_ip,target_port))exceptExceptionase:......
  • 安装Kaspersky Endpoint Security for Windows (12.3.0) 失败,提示安装了 360 Antiviru
    最近,在升级卡巴斯基KES时,部分用户出现安装失败,提示已安装360杀毒软件,需要卸载后再安装。用户已经删除所有360软件。 经过测试,需要在注册表删除:HKEY_CURRENT_USER下面的software里面360和2345的东西。HKEY_LOCAL_MACHINE下面的software中有关360和2345的东西。HKEY_LOCAL_MAC......
  • LOJ3990/LG9602 IOI2023 足球场 题解 (区间DP+精简无用状态)
    首先考虑一个足球场长啥样才是合法的。发现一个点能只拐弯一次到达另一个点,可以分为两种情况:先左右走,再上下走或先上下走,后左右走。无论哪种情况,都要求我们走一步使得和目标点一个轴相同,再走一步使得另一个轴也相同,所以加入把每一行选择的格子看成一个区间(因为如果不连续显然是......
  • CF327C Magic Five 题解
    CF327CMagicFive搬运工单调队列优化DP加等比数列求和首先\(5\)的倍数要求末尾是\(0\)或\(5\)所以我们只用看给定字符串的\(0\)和\(5\)就好,我们钦定他是最终的数的末尾。在他之前的选择删掉,在他之后的全部删掉,方案数就是\(2^{pow-1}\),答案累加就可以了。容易想到......
  • CF-91-B-单调栈+二分
    91-B题目大意给定一个长为\(n\)的序列\(a\),对于每个\(a[i]\),你需要找到一个\(j\)满足\(a[i]>a[j]\)且\(j-i\)最大。Solution逆序遍历,维护一个单调递减的栈,如果当前枚举的\(a[i]\)小于栈顶元素,则入栈。如果\(a[i]\)大于栈顶元素,那么后面的元素如果大于\(a[i]\),那么也大于栈顶......
  • CF-292-D-并查集
    292-D题目大意给定一张无向图,由\(n\)个顶点\(m\)条边。有\(q\)次询问,每次询问将\([l,r]\)的边删去,问图中有多少连通分量。Solution涉及连通分量,尝试应用并查集解决。记录一个前缀并查集\(pre[i]\),表示前\(i\)条边连通后的图;和一个后缀并查集\(suf[i]\),表示后\(m-i\)条边连通......
  • 动态 DP
    序列——线段树维护矩阵转移首先,我们需要普通DP方程改为矩阵乘法或广义矩阵乘法形式,可能会增加一些状态,然后用线段树维护矩阵乘法即可。这个模型推荐使用横向量乘方阵的形式,可以直接从左往右乘。树——重链剖分原理首先,记录每个节点的轻儿子对这个节点DP数组的贡献,然后用......
  • CF1424M Ancient Language 题解
    1.题意描述一本字典中有\(r\)\((1\leqr\leq10^6)\)个单词,单词长度不超过$10^3$,所有字母都是小写英文字母,但字母排序不是按英文字母排序,求所有出现字母的一种排序,如果不存在,输出"IMPOSSIBLE"。2.题目分析由排序规则可知,对于字符串\(s\)和\(t\),\(s\)排在\(t\)......
  • CF618C Constellation 题解
    题意描述给定\(n\)个点(\(n\leq10^5\)),找到三个点满足这三个点不在同一直线上且三个点构成的三角形中不包含其他点,保证所有点不会在同一直线上。题目分析首先必然每一个点都可以作为一组解中的点。不妨其中一个点编号为\(1\)。找一个点作为第二个点,为了使没有点在这条边上,这......
  • CF1036F Relatively Prime Powers 题解
    题目分析对于一个不合法的数\(x(x\ge2)\),设\(x=\prodp_i^{r_i}\),令\(g=\gcd(r_1,r_2,\ldots,r_k)\),则\(x=\left(\prodp_i^{r_i/g}\right)^g\),所以\(x\)是一个正整数的\(g\)次方。所以可以枚举上文的\(g\),把每一类不合法方案排除掉,就是答案。设\(f(i)\)表示\(2\)......