1.暴力30分
ybt
未通过
测试点 | 结果 | 内存 | 时间 |
测试点1 | 答案正确 | 612KB | 2MS |
测试点2 | 答案正确 | 620KB | 8MS |
测试点3 | 答案正确 | 620KB | 7MS |
测试点4 | 运行超时 | 576KB | 997MS |
测试点5 | 运行超时 | 580KB | 998MS |
测试点6 | 运行超时 | 584KB | 1002MS |
测试点7 | 运行超时 | 584KB | 998MS |
测试点8 | 运行超时 | 580KB | 997MS |
测试点9 | 运行超时 | 584KB | 998MS |
测试点10 | 运行超时 | 588KB | 998MS |
LOJ
LUOGU
暴力30分代码如下:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
LL cnt[12];
int main(){
LL lt,rt,i,x;
int j;
scanf("%lld%lld",<,&rt);
for(i=lt;i<=rt;i++){
x=i;
while(x){
cnt[x%10]++;
x/=10;
}
}
for(j=0;j<=9;j++)printf("%lld ",cnt[j]);
return 0;
}
2.数位DP
考虑001,100对于统计0的数量时,影响是不同的,该题需要考虑前导0.
该题应有[10]这一维数组,用于区分0-9.
设状态dp[pos][cnt]表示已经考虑到了前 pos位,目前的某个数码 cur的个数为 cnt 。
我们可以转移:f[pos][cnt]=∑f[pos−1][cnt−(now==cur)],其中 now表示考虑的第pos位上的数码。
为什么选pos,cnt,该dp中的两个维度含义,是由转移方程决定。
ybt
通过
测试点 | 结果 | 内存 | 时间 |
测试点1 | 答案正确 | 620KB | 1MS |
测试点2 | 答案正确 | 604KB | 2MS |
测试点3 | 答案正确 | 608KB | 2MS |
测试点4 | 答案正确 | 608KB | 2MS |
测试点5 | 答案正确 | 612KB | 2MS |
测试点6 | 答案正确 | 612KB | 2MS |
测试点7 | 答案正确 | 608KB | 2MS |
测试点8 | 答案正确 | 604KB | 2MS |
测试点9 | 答案正确 | 616KB | 2MS |
测试点10 | 答案正确 | 616KB | 2MS |
LOJ
LUOGU
数位DP代码如下:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
LL dp[15][15];
int cur;//当前处理的数字
int bit[15];
LL dfs(int pos,int cnt,bool lead,bool limit){
LL ans=0;
int up,i;
if(pos==-1)return cnt;
if(!limit&&!lead&&dp[pos][cnt]!=-1)return dp[pos][cnt];
up=limit?bit[pos]:9;
for(i=0;i<=up;i++){
if(cur==0){//cur是0
ans+=dfs(pos-1,cnt+(i==0&&!lead),i==0&&lead,i==up&&limit);//cnt+(i==0&&!lead)只统计非前导0的情况
}else{//cur是1-9
ans+=dfs(pos-1,cnt+(i==cur),i==0&&lead,i==up&&limit);
}
}
if(!limit&&!lead)dp[pos][cnt]=ans;
return ans;
}
LL solve(LL x){
int pos=0;
while(x){
bit[pos++]=x%10;
x/=10;
}
return dfs(pos-1,0,1,1);
}
int main(){
LL lt,rt;
scanf("%lld%lld",<,&rt);
for(cur=0;cur<=9;cur++){
memset(dp,-1,sizeof(dp));
printf("%lld ",solve(rt)-solve(lt-1));
}
}