题目大意:有些m位n进制整数非常神奇,乘以2,3,4,..m之后,所得到的数恰好是原数个数字的一个排列,给出m和n,你的任务是保证是否有这样的一个数
解题思路:枚举最后一位,只要知道了最后一位就可以知道其他位的,因为是要乘于2到m的,所以假设最后一位是j的话,那么倒数第2位一定是(j+j)%n,倒数第三位是(j+j+j)%m,由此可以得到,现在只要判断一下所给的数经过计算后是否是原来各数字的一个排列即可
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 410
int tmp[10], ans[10], pos[10], vis[maxn], cnt[maxn], n, m;
bool ck() {
int c[10];
for(int i = 0; i < m; i++)
c[i] = ans[i] = tmp[pos[i]];
c[m] = 0;
for(int k = 2; k <= m; k++) {
for(int i = 0; i < m; i++) {
c[i+1] += (c[i] + ans[i]) / n;
c[i] = (c[i] + ans[i]) % n;
}
if(c[m])
return false;
bool flag = false;
for(int i = 0; i < m; i++)
vis[c[i]]++;
for(int i = 0; i < m; i++)
if(cnt[c[i]] != vis[c[i]])
flag = true;
for(int i = 0; i < m; i++)
vis[c[i]] = 0;
if(flag)
return false;
}
return true;
}
bool dfs(int cur) {
if(cur == m)
return ck();
for(int i = cur; i < m; i++) {
swap(pos[cur],pos[i]);
if(dfs(cur+1))
return true;
swap(pos[cur],pos[i]);
}
return false;
}
bool check(int cur) {
int t = 0;
for(int i = 0; i < m; i++) {
t = (t + cur) % n;
tmp[i] = t;
pos[i] = i;
}
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
for(int i = 0; i < m; i++)
cnt[tmp[i]]++;
return dfs(0);
}
int main() {
while(scanf("%d%d",&m, &n) == 2 && n + m) {
bool flag = false;
for(int i = 1; i < n; i++)
if(check(i)) {
flag = true;
break;
}
if(!flag)
printf("Not found.\n");
else {
printf("%d",ans[m-1]);
for(int i = m - 2; i >= 0; i--)
printf(" %d", ans[i]);
printf("\n");
}
}
return 0;
}