时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld
题目描述
You love doing graph theory problems. You've recently stumbled upon a classical problem : Count the number of 4-cliques in an undirected graph.
Given an undirected simple graph G, a 4-clique of G is a set of 4 nodes such that all pairs of nodes in this set are directly connected by an edge.
This task would be too easy for you, wouldn't it? Thus, your task here is to find an undirected simple graph G with exactly k 4-cliques. Can you solve this task?
输入描述:
The first line of input contains a single integer k (1 ≤ k ≤ 106).
输出描述:
On the first line, output two space-separated integers, n, m (1 ≤ n ≤ 75, 1 ≤ m ≤ n * (n - 1) / 2). On the next m lines, output two space-separated integers denoting an edge of the graph u, v (1 ≤ u, v ≤ n), where u and v are the endpoints of the edge.
Your graph must not contain any self-loops or multiple edges between the same pair of nodes. Any graph that has exactly k 4-cliques and satisfies the constraints will be accepted. It can be proven that a solution always exist under the given constraints.
示例1
输入
1
输出
4 6
1 2
1 3
1 4
2 3
2 4
4 3
说明
In the sample, the whole graph is a 4-clique.
题意:给出一个K(1~1e6),要求构造一个图G满足一下条件:75个点以内,不存在重边,且刚好存在K个(4点完全图).
要求输出该图G,格式为N,M(N个点,M条边),随后M行为u,v.
题解:很明显是到构造题,首先看到这道题都会先暴力跑一波C(n,4),因为这是n个点的完全图存在4点完全图的数量,观察发现题目数据卡的挺紧的,因为当n>=72时C(n,4)才大于1e6.期初我的做法是先取一个K以内的最大T个点的完全图,然后剩下的数量就是K-C(T,4),还有一点可以发现就是对于一个点加入一个完全图时,对答案K上的贡献是C(x,3),这里的x是该点与完全图内任意点连边的数量,从T_max=71,我就猜想是否能够取最少剩下的4个点加入T个点的完全图中从而凑出K,测评姬和背包都证明了我的结论是错误的,那么我只能强行取5个点了(也就是T的最大值变为70),从而能够凑出1e6以内的所有K.(证明可以用背包)
不过对于剩5个点我们需要预处理一个点的情况,不然70^5很明显时间复杂度上会爆.
代码如下:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int maxn = 1e6+10;
int f[maxn];
int C_3(int n) {
return (n - 2)*(n - 1)*n / 6;
}
int C_4(int n) {
return (n - 3)*(n - 2)*(n - 1)*n / 24;
}
void print(int t, int a, int b, int c, int d,int e) {
printf("%d %d\n", t + 5, t*(t - 1) / 2 + a + b + c + d + e);
for (int i = 1; i <= t; i++)
for (int j = i + 1; j <= t; j++) printf("%d %d\n", i, j);
for (int i = 1; i <= a; i++) printf("%d %d\n", i, t + 1);
for (int i = 1; i <= b; i++) printf("%d %d\n", i, t + 2);
for (int i = 1; i <= c; i++) printf("%d %d\n", i, t + 3);
for (int i = 1; i <= d; i++) printf("%d %d\n", i, t + 4);
for (int i = 1; i <= e; i++) printf("%d %d\n", i, t + 5);
}
int main() {
int k, t = 4;
scanf("%d", &k);
while (C_4(t) <= k)t++;
t--;
if (t > 70)t = 70;
k -= C_4(t);
for (int i = 2; i <= 70; i++) f[C_3(i)] = i;
for (int a = 2; a <= t; a++)
for (int b = a; b <= t; b++)
for (int c = b; c <= t; c++)
for (int d = c; d <= t; d++) {
int cnt = C_3(a) + C_3(b) + C_3(c) + C_3(d);
if (cnt > k)break;
if (f[k - cnt]) {
print(t, a, b, c, d, f[k - cnt]);
return 0;
}
}
}