來源
source=%E6%B9%96%E5%8D%97%E7%9C%81%E7%AC%AC%E4%B8%83%E5%B1%8A%E5%A4%A7%E5%AD%A6%E7%94%9F%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E7%AB%9E%E8%B5%9B" style="text-decoration:none; color:rgb(55,119,188)">湖南省第七屆大學生電腦程式設計競賽
一道簡單的類比題:要類比出現的情況,主要要推出一個規律 在邊界的位置時,下一個報數的位置就是 2*n-2。(我也不知道是怎麼推出來的)
這樣就能夠推算出 每一個編號 下一個報數的位置;直接進行推斷。
#include <cstdio>#include <cstring>bool judge(int n)//推斷函數,推斷是否含7,或者是7的倍數{ if( !(n % 7) ) return true; while(n) { if( n % 10 == 7 ) return true; n /= 10; } return false;}int main(){ int n,m,k,i; while(scanf("%d%d%d",&n,&m,&k)&&n&&m&&k) { int count=0; for(i=7;;i++) { if(judge(i)) { int x=i%(2*n-2);//得出的是初始編號 if(x==0) x=2*n-2; if(x==m || (x>=n && 2*n-x==m ))//符合題意的情況 count++; if(count==k) break; } } printf("%d\n",i); } return 0;}
還看到別人的還有一種思路,直接找到規律,依據規律暴力求解。
分成了兩個部分進行考慮,邊界情況就直接是2*n-2,中間的間隔是兩個數迴圈變化的。
#include <cstdio>#include <iostream>using namespace std;bool is7( int n )//推斷{ if( !(n % 7) ) return true; while(n) { if( n % 10 == 7 ) return true; n /= 10; } return false;}int main(){ int n, m, k; while( scanf("%d %d %d", &n, &m, &k) !=EOF && n+m+k ) { int cnt = 0, period = 2 * n - 2; if( n == m || m == 1 )//邊界的情況 { for( int i = m; ; i += period ) if( is7( i ) ) { cnt++; if( cnt == k ) { printf("%d\n", i); break; } } } else { int next = 2 - m; for( int i = m; ; swap( next, i ) )//中間的情況 { next += period; if( is7( i ) ) { cnt++; if( cnt == k ) { printf("%d\n", i); break; } } } } } return 0;}
換一種思路。直接進行類比,依照先順序,後倒序進行類比;
#include <cstdio>#include <cstring>bool judge(int n)//推斷{ if( !(n % 7) ) return true; while(n) { if( n % 10 == 7 ) return true; n /= 10; } return false;}int main(){ int n,m,k,i; while(scanf("%d%d%d",&n,&m,&k)&&n&&m&&k) { int pos=0,count=0,flag=0; for(i=1;i<=n;i++)//順序處理 { pos++; if(i==m) { if(judge(pos)) count++; if(count==k)//搜尋到結果了 { printf("%d\n",pos); break; } } if(i==n) { i=n-1;//進行倒序處理 for(;i>=1;i--) { pos++; if(i==m) { if(judge(pos)) count++; if(count==k) { flag=1; printf("%d\n",pos); break; } } } if(flag) break; i=1;//回溯到順序 } } } return 0;}