Q - count 数字计数
题目大意:求[a,b]间所有的整数中0~9每个数字出现了几次
令f[i]为i位数(算前导零)中每个数出现的次数(一定是相同的,所以只记录一个就行了)
有f[i]=f[i-1]*10+10^(i-1)
然后照例十进制拆分
其中计算[0,999...9]的时候要从1~9枚举最高位,然后其余位调用f[i-1]即可
剩余部分已知位直接乘,未知位调用f[i]
转自:http://blog.youkuaiyun.com/PoPoQQQ/article/details/40075787
感觉自己菜到爆。。。。。。看题解都没搞明白,搞了一晚上,。。。交上代码了、、、、
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long ll;
using namespace std;
ll ans[10],f[20];
void cal(ll x,ll pos)
{
while(x){
ans[x%10]+=pos;
x/=10;
}
}
void dfs(ll x,int flag)
{
int i,j;
ll pos,now;
for(i=1,pos=10;pos<x;++i,pos*=10)
{
for(j=0;j<=9;j++)
ans[j]+=f[i-1]*9*flag;
for(j=1;j<=9;j++)
ans[j]+=pos/10*flag;
}
now= pos/=10;
--i;
while(now<x)
{
while(now+pos<=x)
{
ll temp=now/pos;
cal(temp,pos*flag);
for(j=0;j<=9;j++)
ans[j]+=f[i]*flag;
now+=pos;
}
pos/=10;
--i;
}
}
int main()
{
int i;
ll a,b,pos;
f[1]=1;
for(i=2,pos=10;i<=12;i++,pos*=10)
f[i]=f[i-1]*10+pos;
scanf("%lld %lld",&a,&b);
dfs(b+1,1);
dfs(a,-1);
for(i=0;i<=9;i++){
printf("%lld",ans[i]);
if(i==9)printf("\n");
else printf(" ");
}
return 0;
}
代码数位dp:
/*求出区间内0~9的个数
*/
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
int dp[10][10][10]; //dp[i][j][k] 表示以j开头i位数字 含有数字k的个数
int ans[10][2];
int pos = 0;
vector<int> v;
int work(int n) //求10^n
{
int s = 1, i;
for(i=1; i<=n; i++)
{
s *= 10;
}
return s;
}
int js(int j) //求v[j-1]~v[0]组成的数字
{
int s = 0;
int i;
for(i=j; i>=0; i--)
{
s = s* 10 + v[i];
}
return s;
}
void solve(int x)
{
v.clear();
while(x > 0)
{
v.push_back(x % 10);
x /= 10;
}
int i, j, k;
for(i=v.size(); i>0; i--)
{
for(j=v[i-1]-1; j>=0; j--)
{
for(k=0; k<=9; k++)
{
ans[k][pos] += dp[i][j][k];
if(j==0 && i==v.size() && k==0) //第一位数字取0减去这次0在第一位出现的个数
//以及后面每次0在首位的情况。
{
int t = work(v.size()-1);
while(t > 1){
ans[k][pos] -= t;
t /= 10;
}
}
}
}
ans[v[i-1]][pos] += js(i-2); //第i位数字取原数字需要加 后面组成的数字个数
}
pos++;
}
int main()
{
int a, b;
int i, j, k, kk;
for(i=0; i<=9; i++)
{
dp[1][i][i] = 1;
}
for(i=2; i<=9; i++)
{
for(j=0; j<=9; j++)
{
for(k=0; k<=9; k++)
{
if(j==k){
dp[i][j][k] = work(i-1);
}
for(kk=0; kk<=9; kk++)
{
dp[i][j][k] += dp[i-1][kk][k];
}
}
}
}
while(1)
{
cin >> a >> b;
pos = 0;
memset(ans, 0, sizeof(ans));
if(a == 0 && b == 0){
break;
}
if(a > b){
int t = a;
a = b;
b = t;
}
solve(b+1);
solve(a);
for(i=0; i<=9; i++)
{
cout << ans[i][0] - ans[i][1] << " ";
}
cout << endl;
}
return 0;
}