P2602 [ZJOI2010]数字计数

mac2025-02-11  15

偷得题面

设f[i]代表第i位上不算前导零每个数出现多少次

比如54321

首先是5,,5在万位上,那么个十百千位每个数都会出现至少5*f[bit]次,然后万位上,5以下的数都会出现,然后以此类推

最后加完所有位之后,在处理4321这样的跑不满的零位就好了qwq

代码

#include <bits/stdc++.h> #define int long long using namespace std ; int a , b ; int ten[15] , f[15] ; int cnta[15] , cntb[15] , num[10] ; void work(int x ,int cnt[]) { for(int i = 0 ; i < 10 ; i ++) num[i] = 0 ; int len = 0 ; while(x) {//拆数 num[++len] = x%10 ; x = x / 10 ; } for(int i = len ; i >= 1 ; i --) { for(int j = 0 ; j <= 9 ; j ++) { cnt[j] += f[i-1] * num[i] ; //第i位之后的每位每个数数都会出现i次 } for(int j = 0 ; j < num[i] ; j ++) { cnt[j] += ten[i-1] ;//第i位是x,那么在x之前的都会在出现10^(bit-1)次 } //--------以上只是处理A000000....00这亚子----------// //--------以下处理零位--------// int num2 = 0 ; for(int j = i-1 ; j >= 1 ; j --) { num2 = num2 * 10 + num[j] ;//加上零位 } cnt[num[i]] += num2 + 1 ;// num2是零位,1是最高位 cnt[0] -= ten[i-1] ;//清除前导零 } } signed main () { scanf("%lld%lld",&a,&b) ; ten[0] = 1 ;//10的阶乘,每一位代表多少 for(int i = 1 ; i <= 15 ; i ++) { f[i] = f[i-1] * 10 + ten[i-1] ;//在第i位有数字的时候,每个数码有多少个 ten[i] = 10*ten[i-1] ; } work(a-1,cnta) ;//work(0-x的各数位,统计答案的数组) work(b,cntb) ; for(int i = 0 ; i <= 9 ; i ++) printf("%lld ",cntb[i] - cnta[i]) ; return 0 ; }

举个栗子: 32345

首先 是 5f[0] ,然后4f[1] (也就是4个一位数所有的数,因此当前位数4是没有算上的),然后是3*f[2] (也就是4个两位数所有的数,因此当前位数3是没有算上的)....以此类推

然后我们成功的处理完len-1位(y因为这些位数一定是合法的)后,开始考虑len位,首先,num[len]-1个ten[i-1]次(y因为最后一位不算零头也只能出现这些),然后在填上零头就好了

最新回复(0)