良心Day2
T1:大学
uni
\texttt{uni}
uni
现有一无标号 N 个节点 N 条边的无重边连通无向图,每个点可以染成 M 种颜色中的一
种,问本质不同的染色方案数。
我们称两个染色方案是本质不同的当且仅当不存在一种给节点编号的方案令两种染色
方案形成的邻接矩阵以及对应节点的颜色完全一致。
答案对
998244353
998244353
998244353 取模。
对于 5%的数据,有 N = 1
对于 15%的数据,有 N ≤ 5
对于另外 20%的数据,给定的图是一个环
对于另外 20%的数据, 有 M = 1
对于 100%的数据, 有
N
≤
100000
,
M
≤
1
0
9
N ≤ 100000, M ≤ 10^9
N≤100000,M≤109
解法:环套树Polya定理,用树哈希得到每个点下面的子树形态,然后求环上子树形成循环的最小循环节,求子树的方案数再在环上Polya定理求总的答案。(注意这个题不知为何环上不算翻转置换。。。。。。强行降低难度?)
注意树HASH特别容易撞。。。因为这是一个二维结构,用一维字符串的惯性思维HASH会大样例都过不了。。。。。。HASH中乘一个SIZE或者DEPTH就可以了。
AC Code:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<vector>
#include<stack>
#define maxn 100005
#define mod 998244353
using namespace std;
int n,m;
vector<int>v[maxn];
int info[maxn],Prev[maxn<<1],to[maxn<<1],cnt_e=1;
void Node(int u,int v){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v; }
stack<int>sta;
vector<int>h;
bool vis[maxn],onh[maxn];
void dfs(int now,int ff){
vis[now] = 1;
sta.push(now);
for(int i=info[now];i;i=Prev[i])
if(!vis[to[i]]){
dfs(to[i],i^1);
if(!h.empty()) return;
}
else if(i!=ff){
for(int t = -1;t!=to[i];){
t = sta.top();
sta.pop();
h.push_back(t);
onh[t] = 1;
}
return;
}
sta.pop();
}
#define S 37
#define LL long long
LL hs[maxn];
void ser(int now,int ff){
for(int i=info[now];i;i=Prev[i])
if(to[i]!=ff && !onh[to[i]]){
ser(to[i],now);
v[now].push_back(to[i]);
}
}
bool cmp(const int &u,const int &v){
return hs[u] < hs[v];
}
int siz[maxn],dep[maxn];
void ser2(int now){
siz[now] = 1;
for(int i=0;i<v[now].size();i++)
ser2(v[now][i]),siz[now] += siz[v[now][i]];
sort(v[now].begin(),v[now].end(),cmp);
for(int i=0;i<v[now].size();i++)
hs[now] = hs[now] * S + hs[v[now][i]];
hs[now] = hs[now] * S + 1;
hs[now] = hs[now] * siz[now];
}
int f[maxn],inv[maxn]={1,1};
int F(int x,int m){
f[x] = 0;
for(int i=1,a=m,b=1;i<=x;i++){
f[x] = (f[x] + 1ll * a * b) % mod;
a = 1ll * a * inv[i+1] % mod * (m-i) % mod;
b = 1ll * b * inv[i] % mod * (x-1-(i-1)) % mod;
}
return f[x];
}
int ser3(int now){
int ret = m;
for(int i=0,j;i<v[now].size();){
for(j=i;j < v[now].size() && hs[v[now][j]] == hs[v[now][i]];j++);
int tmp = ser3(v[now][i]);
ret = 1ll * ret * F(j-i , tmp) % mod;
i = j;
}
return ret;
}
LL g[maxn];
int nxt[maxn];
inline int gcd(int a,int b){ return !b ? a : gcd(b,a%b); }
inline int Pow(int base,int k){
int ret=1;
for(;k;k>>=1,base=1ll*base*base%mod)
if(k&1)
ret=1ll*ret*base%mod;
return ret;
}
int FA[maxn];
int main(){
freopen("uni.in","r",stdin);
freopen("uni.out","w",stdout);
scanf("%d%d",&n,&m); m %= mod;
for(int i=2;i<maxn;i++)
inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
for(int i=1,x;i<=n;i++) scanf("%d",&x),FA[i] = x,Node(i,x),Node(x,i);
dfs(1,0);
for(int i=0;i<h.size();i++) ser(h[i],0);
for(int i=0;i<h.size();i++) ser2(h[i]);
for(int i=0;i<h.size();i++) g[i] = hs[h[i]];
nxt[0] = -1;
for(int j=-1,k=0;k<h.size();)
if(j==-1 || g[j] == g[k]) nxt[++k] = ++j;
else j = nxt[j];
int l = h.size() - nxt[h.size()];
if(h.size() % l) l = h.size();
int tmp = 1;
for(int i=0;i<l;i++)
tmp = 1ll * tmp * ser3(h[i]) % mod;
int ans = 0;
for(int i=1;i<=h.size()/l;i++)
ans = (ans + Pow(tmp,gcd(i,h.size()/l))) % mod;
printf("%lld\n",((ans*1ll*inv[h.size()/l])%mod+mod)%mod);
}
T2:道别
farewell
\texttt{farewell}
farewell
Ender 早上任意时刻从数轴上的 0 点以 1 的速度向前走,数轴上有 N 个红绿灯,第 i 个
红绿灯在位置
p
i
p_i
pi,会维持
r
i
r_i
ri 秒红灯,然后维持
g
i
g_i
gi 秒绿灯,从0时刻开始,如此反复。
问 Ender 不需要等红灯就通过数轴的概率以及对于每个红绿灯, 其成为第一个拦下
Ender 的红绿灯的概率。
保证
p
i
p_i
pi 各不相同。
对于 5%的数据, 有
N
=
1
N = 1
N=1
对于 10%的数据,有
N
=
2
N = 2
N=2
对于 30%的数据, 有
N
≤
5
N ≤ 5
N≤5
对于另 10%的数据, 有所有
r
i
+
g
i
r_i+g_i
ri+gi 两两互质
对于另 10%的数据, 满足最小的
r
i
+
g
i
r_i+g_i
ri+gi 能整除所有
r
i
+
g
i
r_i+g_i
ri+gi
对于 100%的数据, 满足
N
≤
500
,
p
i
≤
1
0
5
,
r
i
+
g
i
≤
100
,
1
≤
r
i
、
g
i
N ≤ 500, pi ≤ 10^5, r_i+g_i ≤ 100, 1 ≤ r_i、 g_i
N≤500,pi≤105,ri+gi≤100,1≤ri、gi
神题:
考虑
P
a
=
r
a
+
g
a
P_a = r_a+g_a
Pa=ra+ga与
P
b
=
r
b
+
g
b
P_b = r_b+g_b
Pb=rb+gb互质的情况,
那么根据裴蜀定理,我们可以推出,通过
a
a
a的概率和通过
b
b
b的概率是不相关的,独立的。
那么如果两两互质,对于某个灯
x
x
x,是第一个把他拦下的概率为撞上x的概率
×
∏
y
灯
于
x
前
y
没
有
把
他
拦
下
的
概
率
\times \prod_{y灯于x前}y没有把他拦下的概率
×∏y灯于x前y没有把他拦下的概率
如果一个是另一个的倍数,那么我们可以把小的扩大,然后在大的
P
P
P范围内枚举每一个整点,这样也可以求出对于某个灯
x
x
x,是第一个把他拦下的概率。
那么剩下的就是两个数有公因数但是一个不是另一个的倍数的情况。
这种情况无法处理,考虑化归为前两种情况。
之前我们发现如果我们只从整点时刻出发答案不变,
接下来我们考虑从
i
,
i
+
x
,
i
+
2
x
.
.
.
.
i,i+x,i+2x....
i,i+x,i+2x....时刻出发,然后把不同的时刻的概率加起来求平均值。
(
0
<
=
i
<
x
)
(0<=i<x)
(0<=i<x)
考虑循环节
P
P
P变成了什么,变成了
P
g
c
d
(
P
,
x
)
\frac P{gcd(P,x)}
gcd(P,x)P
如果我们取
x
=
2520
x = 2520
x=2520,那么在
P
<
=
100
P<=100
P<=100的情况下可以满足要么互质要么一个是另一个的倍数,
两种概率分开计算乘起来,再对于不同的
i
i
i求平均值。
完了。
代码据说很短。
T3:葬诗
Unconventional
Problem
/
非传统题目
\texttt{Unconventional Problem / 非传统题目}
Unconventional Problem / 非传统题目
现有一段长文本 P 和一个某些位置能摆放按键的 100100 大小网格状键盘基座,你需
要将 1 到 500 共 500 个不同字符的按键安置在键盘上, 最小化一根手指操作键盘输入 P 时
指尖的水平移动距离。
注意, 指尖必须移动到按键中心才能按下按键, 按下按键产生的竖直移动距离不计入答
案, 键盘基座是一个完美的正 100100 网格, 网格的每一小格都是长宽均为 1 的标准正方
形。
输入文件
本题下发文件包含了键盘基座描述文件 keyboard,文本文件 P。
文本文件 P 即为题目描述中提到的 P, 包含了超过五百万个大于等于 1 小于等于 500 的
整数,每个整数 c 表示一个编号为 c 的字符。 你可以根据 P 的特征设计你的键盘。
键盘基座描述文件 keyboard 包含一个 100*100 的字符网格, 第 i 行第 j 列的字符表示
键盘基座上格点(i,j)的状态,若该字符为空格(‘ ’)则表示该格点可以放置按键,否然不
能放置按键。
答案格式与提交方式
你的答案应被命名为 answer(没有扩展名), answer 应该是一个文本文档,包含 100 行
文本,每一行包含 100 个整数。
位于第 i 行第 j 列的整数 c 如果为 0, 则表示键盘格点(i,j)不放置按键, 否然则表示
格点(i,j)放置能输入第 c 种字符的按键。
本题下发了一个样例答案 sample_answer, 该答案虽然不优但合法, 你可以参考该答案
了解答案应有的格式。
本题也下发有评分器 grader.cpp。 将 grader.cpp 编译为 grader.exe 并将文本文件 P
与其置于同一目录下,可以使用命令‘ grader < answer’来查看你答案的得分。若 grader
崩溃,该答案得 0 分。 否然 grader 将会给出答案的得分, 该得分与正式评测时的实际得分
一致。
提交答案时, 你只需要提交一个合法的 answer 文件即可。
提供一下grader:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <climits>
#include <cstring>
#include <map>
#include <vector>
#include <ctime>
using namespace std;
int mp[105][105];
int pos[505][2];
inline int pw (int a) {return a*a;}
inline double dis (int a, int b, int c, int d) {return sqrt(pw(a-c)+pw(b-d));}
double disa[505][505];
inline int getInt () {
int ret = 0; char ch;
while((ch = getchar()) < '0' || ch > '9') ;
ret = ch-'0';
while((ch = getchar()) >= '0' && ch <= '9') ret = ret*10+(ch-'0');
return ret;
}
void gmark (const char*msg, int mark) {
puts(msg);
printf("该答案得分: %d\n", mark);
exit(mark);
}
const char g[100][101] = {
"@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@ @@@@ @@@@@@@@ @@@@@ @@@@@@ @@@@",
"@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@ @@@@@@@@@@ @@@@ @ @@@@@@ @ @@@ @ @@@@@ @@@@@ @@@@@@@@@@ @",
"@@@@@@@@@@@ @@ @@ @@ @@@@ @@@@@@ @@@@@@@@@@@@ @@@ @@@ @ @@@@@ @ @@@@@@@@@@ @ @@@@@@@@@@@ @@ @@@@@@ ",
"@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@ @@@@ @@@@@@@@@@@@@@@@ @ @@@@@@@@ @ @@@@@ @@ @@@@@@@@ @@@@@",
"@@@@@@@@@@@ @ @@@@@ @@@ @@@@@@@@@@@@@@ @@@@ @@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ @@@ @@@@@ @",
"@@@@@@@@@@@@@ @@@@@@@ @@@@@@@@@@@@@@@@@@@@@@ @@@@@ @ @@@@@@ @@@ @ @@ @@@@@@@ @@ @@@@@@@@@@@@@@@@",
"@@@@ @@@@@@@@@@ @@@@@@@@@@ @@@ @@@@@ @@@@@@ @ @@@ @@ @@@@@@@@@ @@ @@ @@ @@ @@@@@@ @@ @@@@@@@@@@@ @@",
" @@ @@@@@@@@ @@ @ @@ @@@ @@@ @@@@@@@@@@@@@@@@@ @@@@@@@@@@@ @@ @@@ @@@@@@ @@@ @@@ @ @@@@@@@@@@@",
"@@@ @@@@@@@@@@@@ @@@@@ @@@ @ @@ @@@@@@@@ @@@@@@ @@@@@ @ @@@@ @@@@@@ @@@@@@@@@@@@@@@@ @@@@@@@@@@@",
"@@@@@@@@@@@@@@@ @@ @@@@ @@@@@@@@ @@@@ @@@@@@ @@@@@ @ @@@@@ @@ @ @ @@@@ @ @@@@@@@@@@ @@@ @@@@@@@@",
"@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@ @@@@@@@@@@@@@ @@@@@ @@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@ @@@@@@ @@",
"@@ @ @@@ @ @@@ @@@@ @@@@@@ @@@ @@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ @@@@@@@@@@@",
"@@@@@@@ @@@@ @@@@@@ @@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@ @@@@ @@@ @@ @@ @@@@@@ @@@@@@@ @@@@@@@@@@@@@@@",
"@@@ @@@@@@ @@@ @@@@@@@@@@@ @ @ @@@ @ @@@ @@@@@@@@@@@@@@@@ @@@@@ @@ @@@@@@@@@@@@@@@@@@@ @@@@@@",
"@@@@ @@@@@@@ @@@@@@ @ @@@ @@@@@@ @@@ @@@@@@@@@@@@@@@@@@ @ @@ @@@@@@@ @@@@@ @@@@@@@@ @@ @@ @@ ",
"@@@@@@@@ @@@@@@@@@@@@@@ @ @@@@@@ @@@@@ @@@@@@@@@@@@@@@ @@@@ @@@@@ @@@@@@@@@@@@@@@@@ @@@@@@@@@@",
"@ @@@@@@@@@ @@@ @@@@@ @@@@@ @@@@@@@@@@ @@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@ @ @@",
"@@@@@@@@@@@@@ @@@@ @@@@@@@ @@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@ @@ @@@@@@@@@@@ @@@@@@@@@@@@@@ ",
"@@@@@@@@@ @ @@@@@@@@@@ @ @@@ @ @@ @@@@@@@ @@@ @@@@@@@@ @@@@@@@@ @@@ @@@@ @@@@@@@@ @@@@ @@@@@@",
"@@@@ @@@@@@@@@@@ @@@@@@@@@@@@ @@@ @ @@@@@@@ @@@@ @@ @ @@@@@@@@@ @@@@ @@@@@@@@@@@@@@@@@@@@@@ @ @@@",
"@@@@@@@@@ @ @ @ @@ @@@@@@@ @ @ @ @@@ @@@@@ @@@@@@@@@@@ @@ @ @@ @@ @@@@ @@@@@@@@@@@@@@@@ @@@@@",
"@@@@@@@@ @@@@@@@@@@@@@@@ @@@@ @@ @@@ @@@@ @ @@ @@ @@@@@@ @@ @@ @ @@ @@ @@@@@@@@@@@@@@@@@@@@@@@",
"@@@@@@ @@@@@ @ @@ @@@@@@ @@@ @ @@@@@ @ @@ @@@@@@@@@ @ @ @@@@ @@@@@@@@@@@@@@ @@@@@@ ",
"@@@@ @@@@@@@@@ @ @ @@ @@ @ @@@@@ @@ @ @ @@@ @ @@ @@@ @ @ @@@ @@@@ @@@ @ @@@",
"@@@ @@@@@@@ @@ @@@@@@@@@@@ @@@@ @@@ @@@@ @@ @@ @ @@@@@ @ @@ @@@@@@ @@@@ @@@@@@",
"@@@@@@@ @@@ @@@@@ @@@ @ @@ @@@@ @@@@ @@@@ @@ @@@ @@@ @ @@ @ @ @@@@@ @@ @@@@@",
"@@@@@@@@@@ @ @@@ @@@@@@@@@ @@@@@@@@@ @ @@@@@@ @@@@@@ @ @ @@@ @ @ @ @@@@ @@ @@@@@@@@@ @ @",
"@@ @@@@ @@@@@ @@@@@@@ @@@@ @@ @@@@@@@@@@@@@ @@@ @@@ @@@@@@@ @ @@@ @ @@@@@@@@@@ @ ",
"@@@@@@@@@ @@ @@ @@@@@@@@ @ @@ @@@@@@@ @@@@@ @@@ @@@@@ @@ @@ @@@@ @ @@@@@@@@@@ @@@",
"@@ @@@@@@ @ @ @@ @ @@ @@@@ @@ @@@@ @@@@@@ @@ @@@@@ @@@@@@@@@ @@@ @@@@ @@@ @@ @@@ @@@@ @ @",
" @@@@ @@@@@ @ @@@ @@@@@@@ @@ @@@@ @@@@@@@@@@@@@@@@@ @@@@@@@@ @@ @@@ @ @@@ @@@@@@@@@@@@@@@ ",
"@@@@@@ @@@@@@ @@@ @@ @@ @ @@@@ @@@@@ @ @@ @@@@@@@@@@@ @ @@@ @ @@@ @@ @ @@@ @ @@ @@ @ @ @ ",
"@@@@@@@@ @@@@@@@ @@@@@ @@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@ @@@ @@ @@@@@@@@@@@@@@@@@@@@@@@@ @ @ @",
"@@@@@@ @ @@@@@@@@@@@ @ @ @@@@@ @ @@ @@ @@@@@@@@ @@@@@@@@ @@@ @ @ @@@ @@ @@@@@@ @@ @@@ @@ @ ",
" @@@@@@@@@@@ @@@@@@@@@ @@@@@@@@@@@ @@ @@@@@@@@@@@@ @@@@@@@@ @ @@@@ @@@@@ @@@@@@@@@@@@@@@@ @ @ ",
"@ @@@@ @ @@@@@ @@@@@ @ @@@@@@@@@@@ @@@ @@@@@@ @@@@ @@@@@@@@@@@ @@@@@ @@@ @@@ @@@@@ @@@ @ @@@",
"@@@@ @@@@@@@@@@@@@@@ @@@@ @@@@@@@@@@ @@@@@@@@@@@@ @ @@@@@@@@@@@@@@ @ @@ @@@@@@@@@@@@@@@@@@@@ @ ",
" @@@@@@@@@@@@ @@ @@@@@@@@@ @@@@@@@@@@@@ @@@@@ @@@ @@ @@@@@ @@@@@@@@@@ @@@@@@@@@@@@@@@@@@ @@@ @ ",
"@@@@ @@@@@@ @@@ @@@@@@@@ @@@@@ @@@@@ @ @@@@ @@@ @@@ @@@@@@@@@@@ @@@ @ @@@@@@@ @@@@@@@@@@@@ @@ @",
"@@@@@@@@@@@@@@@@@@ @@@@@@@@@ @@@@@@@ @@@ @@ @@@@@@@@@@@@@@@@@@@@@ @@@ @@@@@ @@ @ @@@@ @@@@ ",
"@@ @@@@ @@@@@@@@@@@@@@@@@@@@@ @@@ @ @@@@@@@@@@@@@@@ @@@@@@ @@@ @@@@ @@@@@ @@@@@@@@@ @@ @ @@@ @ @",
"@@@@ @@@@@@@ @@@@@@@@@@@ @@ @@@@@@@@@ @@@@ @@@@@@@@@@ @@@@@@@@ @ @@@ @@@@@ @@@ @@@@@ @@@@ @@ @@ @",
"@@@@@@@@ @@ @@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@ @@@@@@@@@@@@ @@@@@@@@@ @@ ",
"@@@ @@@@@@@@@ @@@@@@@@@@@@ @@@ @@@@ @@@@@@ @@@@@@@@@@ @@@ @@@@ @ @@@@@ @ @@@@ @@@@@@ @@@@ @ @ ",
"@ @@@@@@@@@@@@ @@@ @@ @@@@@ @@@@@@@@@ @ @@@@@@@@@@@@@@@ @@@@@@@ @@@@ @@@@@@ @@ @@ @@ @@ @@@@ @",
"@@@@@@@@@@@@ @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@ @@@@@@@@@ @@@ @ @@@ @@@@@@@@@ @@@@@@@@@@@ @@@@ @@",
" @@@@@ @@@@@@ @@ @@@@@@@ @ @@@ @@ @@@ @@@ @@@@@@ @@@@@@ @ @@@ @ @@@@@@ @@@@@ @@@@@@@@@@@ @ @@@@@ ",
"@@@@ @@@@ @ @@@@@@ @@@@ @ @@@@@@@@@@@@@@@@@@@ @@@@@@@@@ @@@@@@ @ @ @@@@@@@@@@@ @@@ @@ @@@@@ @@@@ ",
"@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@ @ @@@@@ @@@ @@ @ @@@@ @ @@@@@@ @@@ @@@@@ @@@ @@@@@@@@ @@@ @@@@",
"@@@@@ @@@ @@@@@@@ @@@@@@@@@@ @ @ @@@@ @@@@@@@@ @@@@@@@@@@@@@@ @@ @@ @@@ @@ @ @@@@@@ @@@@ @ @@@ @@",
"@ @@@@@@@@@ @@@@@@@@@@@@@ @@@@@ @@@@@@ @ @@@@@@@@@@@@@ @@@@@@@@@ @ @@@ @@ @ @@@@@@@@@@@@ @@ @ @@ @",
"@ @@@@@@ @@@@@@@@ @@@@@@@@@@@ @@@@@@@ @@@@@@@@ @ @@@@@@@@@@@@@@ @ @ @@@ @@@ @ @@@ @@@ @ ",
" @@@@@@@@@ @ @@ @@ @@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@ @@@@@@ @ @@@ @ @@ @ @@@@ @@@ @",
"@@@@ @@@@@@@@@@@@@@ @@@@@@@@ @@@@@@@@@@@@@@@ @@@@@ @ @ @@@@ @@@ @@@@@@@ @ @@@@ @@@@@@@ @@@@@ @ @@ ",
" @@@@@@@@@@ @@@@@@@@@@ @@ @@ @@@@@@@@@@@ @@@@@@@@@@@@@@@ @@ @@ @@@@@@@@ @@@@@ @@@@@@@ @ @ @@@@@@",
"@@ @@@@@@@ @@@ @@@@@@@@@@@ @@@@@@@@ @@@@@@@@@@@ @ @@@@@@@@ @@ @@@@@@ @@@ @ @@ @@ @ @ @ @ @ @ @@",
"@ @@@@@@@ @@@@@@@@@@@@@ @@@ @@@@@@ @@@@@@@ @@@@@@@ @@@@@@@@ @ @@@@@@@@@ @ @ @@@ @ @@@@@ @ @@ @ ",
"@ @@@@@@@@ @@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ @@@@@@@@@@@@@@@ @@ @@@@ @@@@@@@@@@ @@@@",
"@@@@@ @ @@@@ @@ @@@@@ @@@@@@ @@@ @ @@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@ @@@@ @ @@@@@@@@@@ @@ @@@@@@ ",
" @@@@@@@@@@@ @@@ @@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@ @@@ @@@@@@@@@@@@@@ @@ @@@ @@@ @@ @@@ @@@@@@@@",
" @@ @ @ @@@@ @ @@@ @ @@ @@@@@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@ @@@@@@ @@@ @@@@@ @@@@@@@@@@@",
"@@@@@@@@@@@ @ @@@@@@@@@@@@ @@@@@@@@@@@@@ @@@@@@@@@ @@@@@@@@@@ @@@@@@ @ @ @@@@@ @@@@ @ @@@@ @ @@ ",
"@@@@@@@@@@@ @@@@@@@@@@@@@@ @@@@@@ @@@ @@@@@@@@@@@@@ @@ @@ @ @ @@@ @@@@@@@@@@@@@@@@@@@@@@@@",
"@@@ @@@@@@ @@@ @ @@@@@ @@@@@@@@@@@@@@@@@@@@ @@ @@@@@@ @@ @ @@@@ @@@@@@@@@@@@ @@@@ @@@",
"@@@ @@@@@@ @ @@@@@@@@@@@@@@@@@@ @@@@@@ @@@@@@@@ @@@@@@@@@@@@@@ @ @ @@@ @@@@@@@@@@@@@@ @",
"@@@@ @ @@@ @ @@ @@@@ @@@@ @@@@@@@ @@ @@@@@ @@@@ @@@@@@@@ @@@@ @@ @@ @@@@@@@@@@@ @@@@@@@@@@@ ",
"@@@@@@@@@ @ @ @@@@@@@@@ @@@@@@@@@@@ @@@@@@@@ @@@@@ @@@@@ @@@@@ @@ @ @@ @ @@@@@@@@@@@@@@ @@@@@",
"@@ @ @@@@ @@@@@@ @ @@@ @ @@ @@@@@@@@@@@@@@ @ @ @@@@@@@@@@ @@ @@@@@ @@@@ @ @ @@@@@ @ @@@@@@@@@@@",
"@ @ @@@@@@ @@@@@ @@@@ @@ @@@@ @ @@@@ @@ @@@ @@@ @@ @@@@ @@@@ @@@ @ @@@@@@@@@@ @@@@@@ @@@@ @@@@",
"@@@@@@@@@@@@ @ @@@@@ @@@ @@@ @@@@@@ @@ @@ @@@@@@@@@ @ @@@@@ @@ @@ @ @ @@@@ @@@@@@@ @@@ @ @@@",
"@@@@@@@ @@@@@@@@@@@@@@@ @@@@@ @ @ @@ @@ @ @@@@@@@@@ @ @@@ @@@@ @@ @ @@ @@@ @@@@@@@ @@@@@@@@@@",
"@@ @@@@@@@@@ @ @@@@@ @@@@@ @@@@ @ @@ @@@@@ @ @@@ @ @@ @ @ @ @@@ @@@@@@@ @@@@@@@@@@ @@@@ @@@",
"@@@@@@@ @@@@@@@@ @@ @@@@@@@ @@@@@ @@@@@@@ @@@ @@ @@@@@@ @@@@@ @ @ @ @ @@ @@@@@@ @ @@@@@@ @",
" @@@@@@@@@ @@ @@@@@ @@ @@@ @@@ @ @@@ @ @@@@@@@@@@@@@@@@@ @@@ @ @@@@@@@@@@@@@@@@@@@@ @@@@@ @@",
"@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@ @@@ @ @@@@@@@@ @ @ @ @ @@@@@@@@@@@@@@@@",
"@@@@@@@@@@ @ @@ @ @@@@@@@@ @@@ @@@@@ @ @@@@@@@@@@@@ @@@@@@@ @@ @ @ @@@@ @ @@@@@ @@ @ @@@@@@@@@@@@",
"@@@ @@@ @@@@@@@@@@@@@@@@ @ @@@@@@@@@@ @@@@@@@@ @@ @@@ @@@@ @@ @@ @ @@@ @@@@@@@@@ @@@@@@@@@@@@@@@",
"@@@@@@@@@@@@ @ @@@@@@@ @@@@@ @@ @@@ @@@@@@@ @@@@@ @@ @@@@@@@ @ @@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@ @",
"@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@ @@ @@@@@@ @ @ @@@@@@ @@@@@@@ @@@@@@@@@ @@@@@",
"@@@@@@@@@@ @ @@@@ @ @@@@@@ @@@@@@@@@@@@@@@ @@ @@@@@ @@@@ @@@ @@@ @@ @@ @@@@ @@ @@@@ @@@@@@@@@@@@@",
"@@@ @@@@@@@@@@@@@@@@ @ @ @@@@@ @@@@@@ @@@@@@@@@@@@ @@@@@@ @@@ @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@",
"@@@@@@@@@@@@ @@@@@@ @@@@@@ @@@@ @@@@@@@@@@@@@@@@@@ @@@@ @ @@@@@@@@@ @@@@@@@@@ @@@@ @@@@@@@@",
"@@@@@@@@@@ @@@@ @@ @@@@@@@@ @@ @@@@ @@ @@@@ @@@@@@@@@@ @@@@@ @@@@ @@@@@@@@ @@@@@@ @@ @@@@@@@ @@@@",
" @@@@@@@ @@@@@@@@@@@ @@@@@ @@@ @@@@@ @@@@@@@@@@@@@@@@@@@@@@ @@ @@@@@@@@@@@@ @ @@@@@@@@@@@@ @@@",
"@@@@@@@@@@@@@@@@@@ @@@@@@@ @@@@@@@@@@@@@ @ @ @@@@@@@@@@@@@@@@@ @@@@ @@@@ @@@@ @@@@@@@@@@@@@@@ @@@@@",
"@@@ @@@ @@@@@@@@ @@@@@@@@@@@@@@@@@@@@ @ @@@@@@@ @ @@@@@@@@@ @@ @@@@ @@@@@@@@@@@@@@@@@@@ @@@@@@ @",
"@@@@ @@@ @@@@@@@@@@ @@@@@@@@@@ @@@@@ @@@@@@ @@@ @@@@@@@@@@@@@ @@@ @@@@ @@ @@@ @@ @@@@@@@@@@@@@@@@",
"@@@@@@@@@@@ @@ @@ @@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@ @@@@@@@@@@@@@@@ @@@@@@@@@@ @@@@@@@@@ ",
"@@@@@ @ @ @@@@@ @@@@@@@@@@@@@@ @@@@@ @@@@@@@@@@@@@ @@ @@@@@@@@ @@ @ @ @ @@@@@@@@@@@@@@@@@@ @@@@",
"@@@@ @@@@ @@@@@@@ @@ @@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@ @@@ @@@@@@@@ @@@@@@@@@@ @@@@ @ @@@@@@@@ @@ @",
"@@@@@@@@@@@@@@ @@@@@@@@@@@ @@@@@ @@@@@@@@@@@@@@@@@@ @@@@@@ @@@@@ @@@@@@@@@ @ @@ @@@@@@@@@@@@@ ",
"@@@@ @@@@ @@@ @@@ @@@@@@@@@@@@@@@@@@@ @@@@@ @@@@@@@@ @@@@@@ @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@ @@@ ",
"@@ @@ @ @ @@@@ @@@ @ @@@@@@@@@@ @@ @@@@@ @@@@@@@@@@ @@@@@@@@ @ @@@@@@@@@@ @@@@@ @@@@@@ @@@@@ ",
"@ @@@@ @@@@@@@@@@@@@@@@ @@@@@ @@@@@@ @ @@@@@@@ @@@@@@@@@@@@@@@ @@@@@ @@@ @@ @@@@@@@@@@@@@@@@ @@@ ",
"@@ @@@@@@@@@@@@@ @@ @@@@ @@@@@@@@@ @@@ @ @@@@@@@ @@ @@@@ @@@@@@ @@ @@@@@@@ @@@@ @@ @@@@@@@@@@@ ",
"@@@ @@@@@@@@@@@@ @@@@ @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@",
"@@ @@@@@@@ @@@@ @@@ @@@@@@@@@ @@ @ @@@@@ @@@@@@@ @@@@@@ @ @@@ @@@@@@@ @@@@@@@@@ @@@@@ @@@@@@@@@",
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@ @@@ @ @@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@ @@ @@@@@@@@@@@ @ @@@@",
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@ @@@@@@@@@ @@ @@@@@ @@@@@ @@@@ @@@@@ @@@@@@@@@@",
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
};
bool vis[505];
int main () {
freopen("answer","r",stdin);
for(int a = 0; a<100; a++)
for(int b = 0; b<100; b++) {
char str[100];
if(scanf("%s", str) != 1) gmark("答案长度不足", 0);
int len = strlen(str);
for(int i = 0; i<len; i++)
if(str[i] < '0' || str[i] > '9') gmark("出现非法字符", 0);
sscanf(str, "%d", &mp[a][b]);
//printf("%d\n", mp[a][b]);
if(mp[a][b]) {
if(mp[a][b] > 500 || g[a][b] != ' ') gmark("出现非法按键", 0);
if(vis[mp[a][b]]) gmark("相同按键重复出现", 0);
vis[mp[a][b]] = true;
pos[mp[a][b]][0] = a, pos[mp[a][b]][1] = b;
}
}
for(int i = 1; i<=500; i++)
if(!vis[i]) gmark("没有用完所有按键", 0);
for(int i = 1; i<=500; i++)
for(int j = 1; j<=500; j++)
disa[i][j] = dis(pos[i][0], pos[i][1], pos[j][0], pos[j][1]);
freopen("P", "r", stdin);
int lst = getInt(), x = 5000266, k;
double cur = 0;
while(x --) k = getInt(), cur += disa[k][lst], lst = k;
printf("答案合法,指尖移动距离:%.2lf\n", cur);
if(cur <= 43000000) gmark("满分", 100);
else if(cur <= 50000000) gmark("高分", 100-(cur-43000000)/(50000000-43000000)*40);
else if(cur <= 110000000) gmark("还不赖", 60-(cur-50000000)/(110000000-50000000)*30);
else if(cur <= 200000000) gmark("手玩分", 30-(cur-110000000)/(200000000-110000000)*29);
else if(cur <= 250000000) gmark("签到分", 1);
else gmark("抱歉,没有分", 0);
}
出题人的正解:遗传算法。
我的贪心乱搞:
对于出现次数多的点x放到估价高的格子上,放了之后对于和x相邻次数>100的点y搜索格子的邻域就近放置,dfs下去,只需要2e7次。
造answer代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 300005
int a,c[maxn],cnt[maxn],cnt2[505][505],c3[505];
pair<int,int>pr[maxn],c2[maxn];
double sc[200][200];
bool cmp(const int &u,const int &v){ return cnt[u] > cnt[v];}
double sqr(double a){ return a * a; }
bool cmp2(const pair<int,int> &u,const pair<int,int> &v){
return sc[u.first][u.second] > sc[v.first][v.second];
}
bool cmp3(const pair<int,int> &u,const pair<int,int> &v){
return cnt2[u.first][u.second] > cnt2[v.first][v.second];
}
int A[200][200];
int b,in[505];
vector<int>v[505];
int pt = 1;
bool usd[505],vis[505][505];
bool cmp4(const int &u,const int &v){ return in[u] > in[v];}
char s[200][200];
pair<int,int>ser(int x,int y,int d){
for(int i=-d;i<=d;i++)
if(x+i>0 && x+i<=100 && y-d>0 && y-d<=100 && !vis[x+i][y-d] && s[x+i][y-d] == ' ')
return make_pair(x+i,y-d);
for(int i=-d;i<=d;i++)
if(x+i>0 && x+i<=100 && y+d>0 && y+d<=100 && !vis[x+i][y+d] && s[x+i][y+d] == ' ')
return make_pair(x+i,y+d);
for(int i=-d;i<=d;i++)
if(x+d>0 && x+d<=100 && y+i>0 && y+i<=100 && !vis[x+d][y+i] && s[x+d][y+i] == ' ')
return make_pair(x+d,y+i);
for(int i=-d;i<=d;i++)
if(x-d>0 && x-d<=100 && y+i>0 && y+i<=100 && !vis[x-d][y+i] && s[x-d][y+i] == ' ')
return make_pair(x-d,y+i);
return make_pair(0,0);
}
void dfs(int now,pair<int,int>ff){
if(usd[now]) return;
usd[now] = 1;
pair<int,int>n;
if(ff.first){
for(int d=1;;d++){
pair<int,int>tmp = ser(ff.first,ff.second,d);
if(!tmp.first) continue;
n = tmp;
break;
}
}
else{
for(;vis[pr[pt].first][pr[pt].second];pt++);
n = pr[pt];
}
vis[n.first][n.second] = 1;
A[n.first][n.second] = now;
for(int i=0;i<v[now].size();i++)
dfs(v[now][i],n);
}
int main(){
freopen("P","r",stdin);
freopen("answer","w",stdout);
while(scanf("%d",&a)!=EOF){
cnt[a]++;
cnt2[min(a,b)][max(a,b)]++;
b = a;
}
for(int i=1;i<=500;i++) c[i] = i , c3[i] = i;
for(int i=1;i<=500;i++)
for(int j=1;j<=500;j++)
c2[(i-1)*500+j] = make_pair(i,j);
sort(c2+1,c2+1+500*500,cmp3);
sort(c+1,c+1+500,cmp);
for(int i=1;i<=5000;i++){
v[c2[i].first].push_back(c2[i].second),
v[c2[i].second].push_back(c2[i].first);
in[c2[i].first] += cnt2[c2[i].first][c2[i].second];
in[c2[i].second] += cnt2[c2[i].first][c2[i].second];
}
freopen("keyboard","r",stdin);
for(int i=0;i<100;i++)
gets(s[i]);
for(int i=0;i<100;i++)
for(int j=0;j<100;j++)
if(s[i][j] == ' ')
for(int x=0;x<100;x++)
for(int y=0;y<100;y++)
if(s[x][y] == ' ' && (x!=i || y!=j))
sc[i][j] += 1 / sqrt(sqr(x-i) + sqr(y-j));
int cnt = 0;
for(int i=0;i<100;i++)
for(int j=0;j<100;j++)
if(s[i][j] == ' ')
pr[++cnt] = make_pair(i,j);
sort(pr+1,pr+1+cnt,cmp2);
sort(c3+1,c3+1+500,cmp4);
for(int i=1;i<=500;i++){
dfs(c3[i],make_pair(0,0));
}
for(int i=0;i<100;i++)
for(int j=0;j<100;j++)
printf("%d%c",A[i][j]," \n"[j==99]);
}