• 【UVA】P12683 Odd and Even Zeroes


    数位dp

    写在前面的话

    一拿到这个题目,第一反应是找规律,于是写个暴力怒从1打表到3000,结果发现了个循环,瞎几把搞一波,写了2000多B,一测,连样例都过不了。然后,自闭了。。
    更恐怖的是,机房还有人打表掉了60多万,发现了好多好多的循环,结果卵用都没有。。。
    无奈,看波题解,数位dp!!!

    回归正题

    推导过程

    不难发现,这道题目是让我们求:
    对于一个数x,设f(x)表示[0,x]含有5的因子的数的总数,
    对于一个区间[1,n],求任意的x满足(xin [1,n])且f(x)%2==0的x个数
    如果你这没看出来,就别往下看了

    类比10进制,对于一个10进制数x,显然其可以写成:

    [x=a_0 imes 10^0+a_1 imes 10^1+...+a_p imes 10^p ]

    设g(x)表示[0,x]含有10的因子的数的总数,
    那么,

    [g(x)=a_0 imes 0+ a_1 imes 1+ a_2 imes 2+...+a_p imes p ]

    类似的,对于一个5进制数y

    [y=b_0 imes 5^0+b_1 imes 5^1+...+b_q imes 5^q ]

    那么

    [f(y)=b_0 imes 0+b_1 imes 1+...+b_q imes q ]

    这样就可以数位dp了。

    状态定义

    (dp_{pos,is})表示当前到第pos位,当前是否含有偶数个5的因子,满足条件的总数(有点拗口,实在不行可以看代码

    状态转移

    非常easy,见代码

    代码:

    #include<bits/stdc++.h>
    #define int long long//日常写法,不要见怪
    using namespace std;
    int n,A[1000010],dp[100010][3];
    int DFS(int pos,int is,bool lead,bool limit){
    	if(pos==0)return !is;
    	if(!lead&&!limit&&dp[pos][is]!=-1)return dp[pos][is];
    	int up=limit?A[pos]:4,tmp=0;
    	for(int i=0;i<=up;i++){//状态转移
    		int x=(i*(pos-1))&1;
    		tmp+=DFS(pos-1,(is+x)&1,lead&&(i==0),limit&&(i==up));
    	}
    	if(!lead&&!limit)dp[pos][is]=tmp;
    	return tmp;
    }
    int solve(int x){
    	A[0]=0;
    	while(x)A[++A[0]]=x%5,x/=5;
    	return DFS(A[0],0,true,true);
    }
    signed main(){
    	memset(dp,-1,sizeof(dp));
    	while(1){
    		scanf("%lld",&n);
    		if(n==-1)break;
    		printf("%lld
    ",solve(n));
    	}
    	return 0;
    }
    
  • 相关阅读:
    VS2013中web项目中自动生成的ASP.NET Identity代码思考
    Identity角色管理五(添加用户到角色组)
    ASP.NET Core 3.0 使用gRPC
    ASP.NET CORE[练习7]Identity用户登录、最简单的登录验证
    dump解析入门用VS解析dump文件进行排障
    C#之Clone
    git push用法和常见问题分析
    python张量下标操作维度小于张量维度的情况
    Transformer position embedding 位置编码
    图graph的基础知识
  • 原文地址:https://www.cnblogs.com/SillyTieT/p/11197073.html
Copyright © 2020-2023  润新知