The 2016 Asia Regional Contest, Tsukuba Quality of Check Digits Gym - 101158B
题意:某城市公民每个人有一个五位数的id,前四位是basic id,最后一位是校验位,校验位是根据样例给出的表格得到的,设某公民的id为abcde,那么e=((((0$a)$b)$c)$d),每个公民都可能犯错误,例如将一位数字写错或者将相邻的两位调换,于是我们优秀的表格是应该可以判断出错的情况的,我们知道对于正确的id,(((((0$a)$b)$c)$d)$e)=0,但是等于0的不一定都是正确的,不等于0的一定是错误的,我们要求的是对于四位的basic id我们不能检验出来这个是否是正确的id的数量,也就是只要这个id出错的情况可能会被判正确,那么就是不可以的,ans就要加加
做法:直接模拟
坑点:例如1233 33调换之后与原来的值返回值也是一样的,这样即使一样也不能成为不能判断是否正确,因为33调换也是原来的值,这里特殊考虑就可以了。
代码如下:
#include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> using namespace std; int mp[10][10]; int num[10]; int ans; //int vis[10]; int solve_1() { int res = 0; for(int i=0; i<4; i++) { res = mp[res][num[i]]; } return res; } int solve() { int res = 0; for(int i=0; i<=4; i++) { res = mp[res][num[i]]; } return res; } bool ok() { // memset(vis , 0 , sizeof(vis)); int ttmp; for(int i=0; i<5; i++) { ttmp = num[i]; for(int j=0; j<10; j++) { if(j==ttmp) continue; num[i] = j; if(solve()==0) return false; } num[i] =ttmp; } if(num[0] != num[1]) { swap(num[0], num[1]); if(solve()==0) return false; swap(num[0], num[1]); } if(num[1] != num[2]) { swap(num[1], num[2]); if(solve()==0) return false; swap(num[1], num[2]); } if(num[2] != num[3]) { swap(num[2], num[3]); if(solve()==0) return false; swap(num[2], num[3]); } if(num[3] != num[4]) { swap(num[3], num[4]); if(solve()==0) return false; } return true; } int main() { ans = 0; for(int i=0; i<10; i++) for(int j=0; j<10; j++) scanf("%d", &mp[i][j]); for(int i=0; i<10; i++) { for(int j=0; j<10; j++) { for(int p=0; p<10; p++) { for(int q=0; q<10; q++) { num[0] = i; num[1] = j; num[2] = p; num[3] = q; num[4] = solve_1(); if( !ok() ) { ans++; // printf("%d %d %d %d %d \n", num[0], num[1], num[2], num[3], num[4]); } } } } } printf("%d\n", ans); return 0; }