Educational Codeforces Round 90 (Rated for Div. 2) 參與排名人數12840git
[codeforces 1373E] Sum of Digits 十位數百位數乃至更高位的進位不可能發生學習
總目錄詳見https://blog.csdn.net/mrcrack/article/details/103564004spa
在線測評地址http://codeforces.com/contest/1373/problem/E.net
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
E - Sum of Digits | GNU C++17 | Accepted | 31 ms | 3900 KB |
題目大意:尋找知足公式的最小x.若找不到,輸出-1.code
難點:思考了一下,主要涉及進位比較難處理。又想了想,知足條件的x應該有時會比較多,如何找最小?blog
基本思路:get
1.十位數百位數乃至更高位的進位不可能發生,舉例以下it
x=99,k=3 x+0=99 x+1=100 x+2=101 x+3=102 各位位上數字之和9+9+1+0+0+1+0+1+1+0+2=24,對應的n是24 n=24能夠找到比上述x更小的狀況 x=18,k=3 x+0=18 x+1=19 x+2=20 x+3=21 各位位上數字之和1+8+1+9+2+0+2+1=24
2.因要找最小的x,能夠大體斷定x+0,x+1,x+2,......,x+k,這k+1個數,在各個位置上的數字差別很小。io
3.因要找最小的x,低位儘量擺大的數,高位儘量的擺小的數,考慮到要湊成n,故個位上的數須要枚舉(從0枚舉到9)。table
樣例模擬過程以下,如下模擬過程,若閱讀有障礙,可結合AC代碼進行學習。
42 7 4 x的個位是0 0,0+1=1,0+2=2,0+3=3,0+4=4,0+5=5,0+6=6,0+7=7 個位上數字之和0+1+2+3+4+5+6+7=28 還剩42-28=14 14沒法均分爲7+1=8份,此種狀況排除 x的個位是1 1,1+1=2,1+2=3,1+3=4,1+4=5,1+5=6,1+6=7,1+7=8 個位上數字之和1+2+3+4+5+6+7+8=36 還剩42-36=6 6沒法均分爲7+1=8份,此種狀況排除 x的個位是2 2,2+1=3,2+2=4,2+3=5,2+4=6,2+5=7,2+6=8,2+7=9 個位上數字之和2+3+4+5+6+7+8+9=44 還剩42-44=-2 還剩下-2,此種狀況排除 x的個位是3 3,3+1=4,3+2=5,3+3=6,3+4=7,3+5=8,3+6=9,3+7=10(1+0=1) 個位上數字之和3+4+5+6+7+8+9+1=43 還剩42-43=-1 還剩下-1,此種狀況排除 x的個位是4 4,4+1=5,4+2=6,4+3=7,4+4=8,4+5=9,4+6=10(1+0=1),4+7=11(1+1=2) 個位上數字之和4+5+6+7+8+9+1+2=42 還剩42-42=0 還剩下0,此種狀況,十位上數字均分的是0/(1+7)=0 因涉及個位上的進位,x+k對應的十位數是0+1=1 接下來處理x+k 1*10+2=12,12-1=11(注,-1是扣除4+7=11(1+1=2)對應的1+1=2的十位上的1的影響),此處若不明,可結合AC代碼進行研究。 11-7=4此時,算出的便是x=4.
AC代碼以下:
#include <cstdio> #include <algorithm> #define LL long long #define INF (LL)1<<63-1 using namespace std; int p[]={0,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9};//0,1,2,3,4,5,6,7,8,9,10(1+0=1),11(1+1=2),12(1+2=3),13(1+3=4),14(1+4=5),15(1+5=6),16(1+6=7),17(1+7=8),18(1+8=9) LL ans; LL solve(int st,int n,int k){ int i,sum=0; LL ret=0,pow=10;//注意pow=10,從十位開始 for(i=st;i<=st+k;i++)sum+=p[i];//個位之和,已包含進位,這個技巧妙啊 n-=sum;//剩下的和值 if(n<0||n%(k+1))return INF;//n<0表示湊不成n;n%(k+1)!=0表示剩下的數據,沒法均分 n/=(k+1);//平均分爲k+1份,每份的數值 if(st+k>=10)n++;//研究最大的數x+k.n++記錄的是十位的進位 while(n>0){ int tmp=9;//除個位,最高位外的數據 if(n<9)tmp=n;//可能的最高位數據 ret+=tmp*pow; pow*=10; n-=9;//低位,數據越大越好 } ret+=p[st+k];//補回個位,對應x+k數據 if(st+k>=10)ret--;//退位,尾巴多了1,故退去 if(ret>=k)return ret-k; else return INF; } int main(){ int t,i,n,k; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&k); ans=INF; for(i=0;i<=9;i++)//個位上的數值 ans=min(ans,solve(i,n,k));//,printf("i=%d ans=%lld\n",i,ans); if(ans==INF)printf("-1\n"); else printf("%lld\n",ans); } return 0; }