P11223 题解
不算太难但很有意思的一道题,这里提供一下我的构造方法。
考虑限制给到了
我们确定两个状态使其一部分情况最终到这个值,另一部分状态最终到另一个值,这两个值封闭;为了最小化影响,我们直接使这两个值分别为
我们手模一下小数据找找灵感,
2 9 9 9 9 9 9 8 9
9 3 9 9 9 9 9 8 9
9 9 4 9 9 9 9 8 9
9 9 9 5 9 9 9 8 9
9 9 9 9 6 9 9 8 9
9 9 9 9 9 7 9 8 9
9 9 9 9 9 9 8 8 9
9 9 9 9 9 9 9 8 9
显然只能沿着不是
我们沿着
易证
代码实现不难,注意特判
#include<bits/stdc++.h>
//#include<Windows.h>
#define int long long
//#define ll long long
#define double long double
#define fi first
#define se second
//#define ls t[p].l
//#define rs t[p].r
#define y1 yyyyyyyyyyyyyyyy1
using namespace std;
const int N = 3e5 + 10, inf = 1e12, M = 101;
const double eps = 1e-14, pi = 3.1415926, kou = 0.577215669902;
const int mod = 1e9 + 7;
//const int AQX = 9;
mt19937 rnd(time(0) ^ clock());
int random(int l, int r){
return rnd() % (r - l + 1) + l;
}
/*
_ _ _
____ _| |_ | |_ ___| |___ _ _
|_ / || | ' \ | ' \/ -_) / -_) ' \
/__|\_, |_||_|_|_||_\___|_\___|_||_|
|__/ |___|
*/
//struct Graph{
// int head[N], tot = 1;
// struct edge{
// int t;
// int d, fa, f;
// int next;
// }e[N << 1];
// void edge_add(int u, int v, int w = 0){
// e[++tot].next = head[u];
// e[tot].t = v;
// e[tot].d = w;
// e[tot].f = u;
// head[u] = tot;
// }
// void clear(int n){
// for(int i = 1;i <= tot;i++)e[i].t = e[i].f = e[i].d = e[i].next = 0;
// for(int i = 1;i <= n;i++)head[i] = 0;
// tot = 0;
// }
//}g;
//int qmr(int x, int a){
// int ret = 1, p = x;
// while(a){
// if(a & 1)ret = ret * p % mod;
// p = p * p % mod;
// a >>= 1;
// }
// return ret;
//}
int n, k, jc[N], ans[20][20];
signed main(){
int T, lsj;
cin >> lsj >> T;
jc[0] = 1;
for(int i = 1;i <= 12;i++)jc[i] = jc[i - 1] * i % mod;
while(T--){
cin >> n >> k;
if(n == 1 && k == 0){
cout << 2 << " " << 2 << endl;
printf("1 1\n");
continue;
}
cout << n + 1 << " " << n << endl;
for(int i = 1;i < n;i++){
int p = jc[n - i], j = n;
for(;k >= p;k -= p, j--)ans[i][j] = n;
for(;j;j--)ans[i][j] = n + 1;
if(k)ans[i][i] = i + 1;
}
for(int i = 1;i <= n;i++){
for(int j = 1;j < n;j++)printf("%lld ", ans[j][i]);
printf("%lld %lld\n", n, n + 1);
}
}
return 0;
}