http://acm.hdu.edu.cn/showproblem.php?pid=6659
题意:给你d,x,让求满足f(d,n)=n的最大n(n<=x),其中f(d,n)表示数字d在从1到n的数中出现的总次数。
思路:网上真的是有一种神仙思路(找规律,推公式),显然如果f(d,x)=x那么答案就是x,否则让x -= max( 1 , abs(f(d,x)-x)/18 )然后再验,猛地一看感觉很不靠谱,x是1e18岂不是要爆掉?仔细一看abs(f(d,x)-x)和x的数量级是一样的。。(例如让d=1,x=500,一个500,一个100,至于还有个/18无所谓,因为x越大影响越不明显),这样循环次数就不会很多,/18因为f(d,n-1)和f(d,n)最多差18,然后算f(d,x)算是一个板子,就是依次算个位,十位,百位...
复杂度也会很低。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 ll cal(ll n,ll x){ 6 ll cnt = 0,k; 7 for(ll i=1;k=n/i;i*=10){ 8 cnt += (k/10)*i; 9 int cur = k%10; 10 if(cur>x) cnt += i; 11 else if(cur==x) cnt += n-k*i+1; 12 } 13 return cnt; 14 } 15 16 int main(){ 17 ios::sync_with_stdio(0); 18 cin.tie(0); 19 cout.tie(0); 20 int T; 21 cin>>T; 22 while(T--){ 23 ll d,x; 24 cin>>d>>x; 25 while(1){ 26 ll num = cal(x,d); 27 if(num == x){ 28 cout<<x<<endl; 29 break; 30 } 31 x -= max(1LL,abs(num-x)/18); 32 } 33 } 34 return 0; 35 }