NOIP2021 T1 报数
? 傳送門:NOIP2021 T1
題目大意
報數游戲是一個廣為流傳的休閑小游戲。參加游戲的每個人要按一定順序輪流報數,但如果下一個報的數是 7 的倍數,或十進制表示中含有數字 7,就必須跳過這個數,否則就輸掉了游戲。
在一個風和日麗的下午,剛剛結束 SPC20nn 比賽的小 r 和小 z 閑得無聊玩起了這個報數游戲。但在只有兩個人玩的情況下計算起來還是比較容易的,因此他們玩了很久也沒分出勝負。此時小 z 靈光一閃,決定把這個游戲加強:任何一個十進制中含有數字 7 的數,它的所有倍數都不能報出來!
形式化地,設 p(x)p(x)p(x) 表示 x 的十進制表示中是否含有數字 7,若含有則 p(x)=1p(x) = 1p(x)=1,否則 p(x)=0p(x) = 0p(x)=0。則一個正整數 x 不能被報出,當且僅當存在正整數 yyy 和 zzz ,使得 x=yzx = yzx=yz 且 p(y)=1p(y) = 1p(y)=1。
例如,如果小 r 報出了 6 ,由于 7 不能報,所以小 z 下一個需要報 8;如果小 r 報出了 33,則由于 34=17×234 = 17 \times 234=17×2,35=7×535 = 7 \times 535=7×5 都不能報,小 z 下一個需要報出 36 ;如果小 r 報出了 69,由于 70~7970 \sim 7970~79 的數都含有 7,小 z 下一個需要報出 80 才行。
現在小 r 的上一個數報出了 xxx,小 z 想快速算出他下一個數要報多少,不過他很快就發現這個游戲可比原版的游戲難算多了,于是他需要你的幫助。當然,如果小 r 報出的 xxx 本身是不能報出的,你也要快速反應過來小 r 輸了才行。
由于小 r 和小 z 玩了很長時間游戲,你也需要回答小 z 的很多個問題。
分析
? 一看這題,好像很好做嘛,不就是把數字中帶 7 的和這些數的倍數直接篩掉就好了嗎。就像這樣:
/* is[i] 表示第數字 i 可不可以報再取個反 ans[i] 表示的是第 i 個可以報的數字 */ for(int i = 1; i <= 1e7 + 1000; i++){if(is[i]) continue; // 如果不能報就直接跳過int temp = i;while(temp){ // 看這個數字中有沒有 7int ttemp = temp % 10;temp /= 10;if(ttemp == 7) // 如果有就把這個數和它的倍數都標記為不能報的數for(int j = 1; j * i <= 1e7 + 1000; j++) is[i * j] = 1;} } for(int i = 1; i <= 1e7 + 1000; i++)if(!is[i]) ans[++cnt] = i;? 這里要注意,枚舉 iii 的范圍需要在題目的最大的基礎上加上一小段,因為可能題目剛好問你 1e71e71e7 的下一個該報什么數字,這個數就會比 1e7 大。
? 然后是查詢的部分,我們只需要在 ans 數組里面二分就可以了。根據題目給出的這個數,找到在 ans 數組中大于等于它的第一個數,因為我們找的是大于等于的數,所以如果我們找到的剛好等于題目給的數那么答案就是 ans 數組中的下一個數。如果我們找到的這個數大于題目給的數,那么題目要求的這個數就在 ans 數組里不存在,也就說明這個數不能被報出來,也就輸出 -1。就是這樣:
while(t--){int x = in; // 輸入int idx = lower_bound(ans+1, ans+cnt+1, x) - ans; // 在數組中二分,找到大于等于 x 的第一個數的下表if(ans[idx] != x) cout << -1 << endl; // 如果這個數和 x 不相等,說明 x 不在 ans 數組中,所以輸出 -1else cout << ans[idx + 1] << endl; // 否則就輸出下一個數 }代碼
? 完整代碼如下:
#include<bits/stdc++.h> using namespace std; #define in read() #define MAXN (int)(1e7 + 1000) #define endl '\n'inline int read(){int x = 0; char c = getchar();while(c < '0' or c > '9') c = getchar();while('0' <= c and c <= '9'){x = x * 10 + c - '0'; c = getchar();}return x; }int t = 0;int cnt = 0; int ans[MAXN] = { 0 }; bool is[MAXN] = { 0 };void init(){for(int i = 1; i <= 1e7 + 1000; i++){if(is[i]) continue;int temp = i;while(temp){int ttemp = temp % 10;temp /= 10;if(ttemp == 7)for(int j = 1; j * i <= 1e7 + 1000; j++) is[i * j] = 1;}}for(int i = 1; i <= 1e7 + 1000; i++)if(!is[i]) ans[++cnt] = i; }int main(){freopen("number.in", "r", stdin);freopen("number.out", "w", stdout);init();t = in;while(t--){int x = in;int idx = lower_bound(ans+1, ans+cnt+1, x) - ans;if(ans[idx] != x) cout << -1 << endl;else cout << ans[idx + 1] << endl;}return 0; }總結
以上是生活随笔為你收集整理的NOIP2021 T1 报数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使c语言程序变成流程图的软件,c语言流程
- 下一篇: 计算机课演示文稿模板,计算机网络拓扑结构