链接: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");
}
}