• [BZOJ]3679 数字之积


    题意

    一个数x各个数位上的数之积记为f(x) <不含前导零>
    求[L,R)中满足(0<f(x)<=n)的数的个数

    题解

    (第一次独立做出来的数位dp)
    虽然也是很简单,熟悉数位dp的套路就行了。
    数位dp是不是只要写个爆搜然后加个记忆化就行了啊?
    先写了的爆搜, (dfs(i, limit, x, lead))表示当前搜到第i位,是否受顶端限制为limit,前面的乘积为x,当前是否为前导0为lead。

    然后加记忆化因为这个dp是求(dfs)函数的值,只需要保存几个自变量对应的因变量值就行了,但是x范围很大。
    但是其实x能取的值很少,因为x包含的质因子只有10以内的,用map存状态就行了(其实是运气好,并没有分析x的范围)。

    #include <bits/stdc++.h>
    #define int long long
    #define Mid ((l + r) >> 1)
    #define lson (rt << 1)
    #define rson (rt << 1 | 1)
    using namespace std;
    int read(){
    	char c; int num, f = 1;
    	while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
    	while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';
    	return f * num;
    }
    map<int, int>f[109][2][2];
    int n, len, a[109];
    char s[109];
    int dfs(int i, int limit, int x, int lead) {
    	if(x > n || x <= 0) return 0;
    	if(f[i][limit][lead].count(x)) return f[i][limit][lead][x];
    	if(i == len + 1) return x <= n && lead == 0;
    	int up = (limit ? a[i] : 9), ans = 0;
    	if(lead) ans += dfs(i + 1, 0, x, 1);
    	for(int p = 1; p <= up; p++) {
    		ans += dfs(i + 1, limit && p == up, x * p, 0);
    	}
    	f[i][limit][lead][x] = ans;
    	return ans;
    }
    int query(int x) {
    	len = 0;
    	for(int i = 0; i < 109; i++)
    		for(int j = 0; j <= 1; j++) 
    			for(int k = 0; k <= 1; k++)	
    				f[i][j][k].clear();
    	while(x) {
    		a[++len] = x % 10;
    		x /= 10;
    	}
    	reverse(a + 1, a + 1 + len);
    	return dfs(1, 1, 1, 1);
    }
    signed main()
    {
    	int ans = 0, l, r;
    	n = read();
    	l = read(); r = read();
    	printf("%lld
    ", query(r - 1) - query(l - 1));
    	return 0;
    }
    /*
    dfs(i, x, z)表示前i位,是否顶到上限,积为z的方案数。
    */
    
  • 相关阅读:
    Spring自动代理机制
    JUnit4 详解
    struts2 OGNL
    loj4j的配置跟使用
    junit浅学笔记二
    shell变量设置
    zookeeper使用
    [zz]Linux kernel map
    glog 使用中存在的问题
    shell中特殊字符(串)
  • 原文地址:https://www.cnblogs.com/onglublog/p/14392586.html
Copyright © 2020-2023  润新知