鏈接:http://codeforces.com/problemset/problem/550/C
題意:給你一個長度最大爲100的整數,問你能不能去掉這個整數裏面的數字,使去掉後的整數能被8整除。
思路:
題解的數學方法:一個數要是能被8整除,只要後面三位能被8整除就可以了。因爲一個數總可以寫成num =...... 1000 * x + 100 * y + 10 * z + t的形式,1000能被8整除,所以大於等於1000以上的就不用考慮,只要考慮後三位即可,那麼直接暴力從原整數中取出1,2,3長度的數,只要有能被8整除的就是答案。
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(i,a,b) for(int i = a;i <= b;i++)
using namespace std;
typedef long long ll;
const int maxn = 75;
const int INF = 0x3f3f3f3f;
string s;
vector<string> vec[4];
int main()
{
while(cin>>s)
{
for(int i = 0;i < 4;i++)vec[i].clear();
int len = s.length();
for(int i = 0;i < len;i++)
{
string s1 = "";
s1 += s[i];
vec[1].push_back(s1);
for(int j = i + 1;j < len;j++)
{
string s2 = s1;
s2 += s[j];
vec[2].push_back(s2);
for(int k = j + 1;k < len;k++)
{
string s3 = s2;
s3 += s[k];
vec[3].push_back(s3);
}
}
}
int ans = -1;
int num;
for(int i = 1;i <= 3;i++)
{
for(int j = 0;j < vec[i].size();j++)
{
if(i == 1){
num = vec[i][j][0] - '0';
}else if(i == 2){
num = (vec[i][j][0] - '0') * 10 + (vec[i][j][1] - '0');
}else if(i == 3){
num = (vec[i][j][0] - '0') * 100 + (vec[i][j][1] - '0') * 10 + (vec[i][j][2] - '0');
}
// cout<<num<<endl;
if(num % 8 == 0)
{
ans = num;
break;
}
}
if(ans != -1)break;
}
if(ans == -1)
{
printf("NO\n");
}
else
{
printf("YES\n%d\n",ans);
}
}
}
自己的dp方法(題解裏也有說,不知道一不一樣):
設狀態轉移方程爲dp[i][j],表示取到第i位數時餘數爲j的情況是否存在,存在則dp[i][j] = 1。然後從前向後枚舉,如果j=0這種情況出現則說明有符合答案,那麼根據輔助數組mark往前找答案,將答案還原
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(i,a,b) for(int i = a;i <= b;i++)
using namespace std;
typedef long long ll;
const int maxn = 102;
const int INF = 0x3f3f3f3f;
string s;
int dp[maxn][8];
int mark[maxn][8][2];
int main()
{
while(cin>>s)
{
int len = s.length();
mem(dp,0);
mem(mark,0);
int qian = -1,hou = -1;
for(int i = 0;i < len;i++)
{
int val = (s[i] - '0') % 8;
dp[i][val] = 1;
mark[i][val][0] = -1;
mark[i][val][1] = -1;
if(s[i] == '8' || s[i] == '0')
{
qian = s[i];
break;
}
}
if(qian != -1)
{
puts("YES");
printf("%c\n",(char)qian);continue;
}
for(int i = 1;i < len;i++)
{
int now = s[i] - '0';
for(int j = 0;j < i;j++)
{
for(int k = 0;k < 8;k++)
if(dp[j][k] == 1)
{
int cur = k * 10 + now;
cur %= 8;
if(cur == 0)
{
qian = i,hou = cur;
}
mark[i][cur][0] = j;
mark[i][cur][1] = k;
dp[i][cur] = 1;
}
if(qian != -1)break;
}
if(qian != -1)break;
}
if(qian == -1)
{
puts("NO");continue;
}
string ans = "";
while(1)
{
ans += s[qian];
int tempqian = qian,temphou = hou;
qian = mark[tempqian][temphou][0];
hou = mark[tempqian][temphou][1];
if(qian == -1)break;
}
reverse(ans.begin(),ans.end());
puts("YES");
for(int i = 0;i < ans.length();i++)
{
printf("%c",ans[i]);
}
printf("\n");
}
}