custoj 233-很有趣的一道題
阿新 • • 發佈:2018-12-20
描述
lzp喜歡搞笑數,所有搞笑的數都非常地搞笑,比如23333、233333、2333333。
所以說,一個搞笑數的每位上只能出現2或3
現給定一個正整數n,求一個搞笑數x,要求x是n的整數倍。
輸入
多組資料每行一個正整數n,n<=100000
輸出
對於每組資料,輸出一個搞笑數x,x的位數不能超過500若不存在這樣的搞笑數,輸出Unhappy
輸入樣例 1
4
輸出樣例 1
32
輸入樣例 2
6
輸出樣例 2
222222222222222222222222
來源
ccw630
剛看到這道題我是矇蔽的,請教了杭電的大佬才做出來。
主要還是運用了dp的思想 s[x][y]表示當該數除以n餘數為y時位數為x的解。比如不能整除2的個位數的一個解即為s[1][2]=2;顯然,一個合法的解就是s[x][0],x可以為任意數。然後如果當前s[x][y]有解(不為空時),可以得到s[x+1][(y+2)%n]="2"+s[x][y],換成3同理。用文字表示就是在解的前面加上一位2 相當於給餘數前面加上一位2然後對n取模(判斷整除或者超過),這就是核心思想了。我是萬萬想不到的。
除此以外,由於x位的資料只與x-1位的資料相關聯,所以可以採用滾動陣列,因為只要找一個就行,本身演算法就是從小到大判斷。
AC程式碼:
#include <iostream> #include <cstdio> #include <cstring> #include <string> using namespace std; const int maxn=100010; string s[2][maxn]; int a[510]; string two="2",three="3"; int main() { int n; while(scanf("%d",&n)!=EOF) { if(n%5==0) { cout<<"Unhappy\n"; continue; } a[1]=1%n; for(int i=2;i<501;i++) a[i]=a[i-1]*10%n; for(int i=0;i<n;i++) s[1][i]=s[0][i]=""; s[1][2%n]="2",s[1][3%n]="3"; if(s[1][0]!="") cout<<s[1][0]<<endl; else { int flag=0; for(int i=2;i<501;i++) { int t2=2*a[i]%n,t3=3*a[i]%n; for(int j=1;j<n;j++) { if(s[(i+1)%2][j]!="") { s[i%2][(j+t2)%n]=two+s[(i+1)%2][j]; s[i%2][(j+t3)%n]=three+s[(i+1)%2][j]; } } for(int j=1;j<=n;j++) s[(i+1)%2][j]=""; if(s[i%2][0]!="") { cout<<s[i%2][0]<<endl; flag=1; break; } } if(!flag) cout<<"Unhappy\n"; } } return 0; }