如何提高博客访问量?
数字之积题目链接
题意:一个数x各个数位上的数之积记为f(x) <不含前导零> 求[L,R)中满足0<f(x)<=n的数的个数
0<L<R<10^18 , n<=10^9
解题思路:如果打表的话就会发现f(x)只有4000多个…所以可以去离散化。当然,如果你是数学带佬,你也可以直接发现所有的素因子只有2,3,5,7,所以最后的 乘积只会有几千种(我不知道怎么算出来的qwq)。只要发现了这一点,这道题就变得比较简单了。构建dp[pos][mul] 去维护长度为pos时,乘积为mul的数量。
错误原因:
- 想不到f(x)可以离散化
- dp数组暴int了
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define LL long long
#define MT(a,b) memset(a,b,sizeof(a))
const int mod=10007;
const int maxn=1e5+5;
const int ONF=-0x3f3f3f3f;
const int INF=0x3f3f3f3f;
LL dp[20][maxn];
map<LL, int>lsh;
int num[30];
int cnt;
LL n;
void get_lsh(LL x){
if (lsh.count(x)==1||x>n) return;
lsh[x]=++cnt;
for (int i=1;i<=9;i++)
get_lsh(x*i);
}
LL dfs(int pos,LL mul,bool limit,bool lead){
if (mul>n||(!lead&&mul==0)) return 0;
if (pos==0) return (mul>0&&mul<=n);
if (dp[pos][lsh[mul]]!=-1&&!limit) return dp[pos][lsh[mul]];
LL ans=0;
int up=limit?num[pos]:9;
for (int i=0;i<=up;i++){
ans+=dfs(pos-1,lead?i:i*mul,limit&&i==num[pos],lead&&i==0);
}
if (!limit) dp[pos][lsh[mul]]=ans;
return ans;
}
LL solve(LL m){
int pos=0;
while (m){
num[++pos]=m%10;
m/=10;
}
return dfs(pos,0,true, true);
}
int main (){
lsh.clear();
cnt=0;
LL a,b;
scanf("%lld%lld%lld",&n,&a,&b);
get_lsh(1);
MT(dp,-1);
printf("%lld\n",solve(b-1)-solve(a-1));
return 0;
}