因为只有std,没有自我实现,所以是无码专区
problem
给定一个 qqq 进制的乘法表,每个字符代表着 0∼p−10\sim p-10∼p−1 不同的数字。
求每个字符代表的数字。保证有解。
×\times× | A | B | C | D |
---|---|---|---|---|
A | CD | BB | DC | BA |
B | BB | BB | BB | BB |
C | DC | BB | DB | BC |
D | BA | BB | BC | BD |
i.e.
CD\text{CD}CD 表示的是 ppp 进制下的结果,即:A×A=C⋅p+DA\times A=C·p+DA×A=C⋅p+D。
上述例子的答案为:A=3,B=0,C=2,D=1\text{A=3,B=0,C=2,D=1}A=3,B=0,C=2,D=1。
时限:10s256MB10s\ 256MB10s 256MB
我的想法
表示 000 的字符非常好找:所在“十字架”结构全都是该字符。
表示 111 的字符也很好找:所在“十字架”结构高位全是 000 字符,其余字符在低位出现的次数相同。
- 对于
q≤50
的 50%50\%50% 部分
显然,所有代表数字 <q<\sqrt{q}<q 的字符,自乘后高位一定是 000 对应字符,低位字符一定表示一个平方数。
找出所有 <q<\sqrt{q}<q 的字符,全排列枚举每个字符对应的数字,然后搜索乘法表是否冲突。
时间复杂度 O(q!q2)O(\sqrt{q}!q^2)O(q!q2)。
- 对于
q≤2000
的 100%100\%100% 部分
很容易知道在 ppp 进制下,有哪些 ≥q\ge \sqrt{q}≥q 的数字平方高位是相同的,即某数字代表字符在高位出现次数是易得的。
如果某些数字出现高位的次数相同,就全排列匹配搜索,否则唯一就可以确定字符和数字的匹配。
时间复杂度未知——只是认为这样可以。
solution
000 对应字符很好找。
然后对于 1∼q−11\sim q-11∼q−1 的每个元素 iii,其在乘法表中,对应的十位一定是 0∼i−10\sim i-10∼i−1,一共是出现了 iii 个不同的数字。
直接统计十位的个数,然后匹配即可。
时间复杂度 O(n2)O(n^2)O(n2)。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>#define N 4005
#define M 15
#define mod 1000000007
#define mod2 100000000
#define ll long long
#define maxi(a,b) (a)>(b)? (a) : (b)
#define mini(a,b) (a)<(b)? (a) : (b)using namespace std;int cnt;
int p;
int i, j;
int a[N][N];
int c[N][N];
int cc[N];
int ans[N], pp[N];int main() {freopen("multiplication.in", "r", stdin);freopen("multiplication.out", "w", stdout);cnt = 1;scanf("%d", &p);for (i = 0; i < p; i++) {for (j = 1; j <= p; j++) {scanf("%d", &a[i][2 * j - 1]);cc[ a[i][2 * j - 1] ]++;scanf("%d", &a[i][2 * j]);cc[ a[i][2 * j] ]++;}}int ma = cc[0];int index = 0;for (i = 0; i < p; i++) {if (cc[i] > ma) {ma = cc[i];index = i;}}ans[0] = index;memset(cc, 0, sizeof(cc));for (i = 0; i < p; i++) {for (j = 1; j <= p; j++) {if (c[i][ a[i][2 * j - 1] ] == 0) {c[i][ a[i][2 * j - 1] ] = 1;cc[i]++;}}if (cc[i] == 1) {if (ans[0] != i)ans[1] = i;} else {ans[ cc[i] ] = i;}}for (int i = 0; i < p; i++)pp[ans[i]] = i;for (i = 0; i < p; i++)printf("%d%c", pp[i], " \n"[i == p - 1]);
}