《Divisibility by Eight》
非常好的一个题。
如果不是看到dp的tag,我可能真不会往dp去想。
首先状压去枚举肯定不行,因为最多100位。
经过仔细思考之后我得出了一个dp状态。
dp[i][j][k] - 表示a[i]为第j位且余数为k的值。
在验证过后,我发现这个状态很可做。
然后就开始推了,并不是很难推,但是这里有一个问题,这个数太大存不下。
所以我一开始用了python去写,但是python的三维数组存在了一个值覆盖的问题,怎么都写不对。
于是我开始思考,直接用string去存答案即可,然后在中间所有情况都只去记录一个模数就行了。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 1e5 + 5; const int M = 1e3 + 5; const LL Mod = 1000000; #define pi acos(-1) #define INF 1e12 #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } } using namespace FASTIO; string dp[105][105][10],ans;//dp[i][j][k] - i为第j位对8取模的余数为k int a[105]; LL quick_mi(LL a,LL b){ LL re = 1; while(b){ if(b & 1) re = re * a % 8; a = a * a % 8; b >>= 1; } return re; } int main() { string s;cin >> s; int n = s.size(),len = 0,f = 0; for(int i = s.size() - 1;i >= 0;--i) a[++len] = s[i] - '0'; for(int i = 1;i <= n;++i) { if(a[i] == 0) { f = 1; break; } } if(f) { printf("YES\n0\n"); } else { for(int i = 1;i <= n;++i) { for(int j = 1;j <= i;++j) { int ma = quick_mi(10,j - 1) * a[i] % 8; if(j == 1) { dp[i][j][ma] = a[i] + '0'; } else { for(int k = 0;k < 8;++k) { for(int m = 1;m < i;++m) { if(dp[m][j - 1][k].size() != 0){ int yu = (k + ma) % 8; char c = a[i] + '0'; dp[i][j][yu] = c; dp[i][j][yu] += dp[m][j - 1][k]; } } } } if(dp[i][j][0].size() != 0){ ans = dp[i][j][0]; } } } if(ans.size() != 0) cout << "YES" << "\n" << ans << "\n"; else printf("NO\n"); } system("pause"); return 0; }