2017-2018 ACM-ICPC, NEERC, Northern Subregional Contest

Contest Info


传送门

Solved A B C D E F G H I J K L
9 / 12 O O O - O - Ø Ø O - O O
  • O 在比赛中通过
  • Ø 赛后通过
  • ! 尝试了但是失败了
  • - 没有尝试

Solutions


A. Auxiliary Project

简单dp即可。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/11 13:13:46
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e6 + 5;
 
const int mp[] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6};
const int val[] = {-1, -1, 1, 7, 4, 5, 9, 8, -1, -1, -1};
int n;
int dp[N];
 
void run() {
    freopen("auxiliary.in", "r", stdin);
    freopen("auxiliary.out", "w", stdout);
    cin >> n;
    memset(dp, -1, sizeof(dp));
    dp[0] = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j < 10; j++) if (val[j] != -1 && i >= j && dp[i - j] != -1) {
            dp[i] = max(dp[i], dp[i - j] + val[j]);
        }   
    }
    cout << dp[n] << '\n';
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

B. Boolean Satisfiability

开心签到。

Code
#include<cstdio>
#include<cstring>
using namespace std;
#define TM "boolean"
 
char buf[1007];
int chs[57][2];
int main() {
#ifndef LOCAL
	freopen(TM".in", "r", stdin);
	freopen(TM".out", "w", stdout);
#endif
	scanf("%s", buf);
	int l=strlen(buf);
	memset(chs,0,sizeof chs);
	int qf=false;
	for(int i=0; i<l; i++) {
		switch(buf[i]) {
			case '~':
				qf=true;
				break;
			case 'a' ... 'z':
				chs[buf[i]-'a'][qf]=1;
				qf=false;
				break;
			case 'A' ... 'Z':
				chs[buf[i]-'A'+26][qf]=1;
				qf=false;
				break;
		}
	}
	long long ans=1;
	bool ok=false;
	for(int i=0; i<52; i++) {
		if(chs[i][0]&&chs[i][1])  ok=true;
	}
	if(!ok) {
		for(int i=0; i<52; i++) {
			if(chs[i][0] || chs[i][1]) 
				ans*=2;
		}
		ans--;
	} else {
		for(int i=0; i<52; i++) {
			if(chs[i][0]||chs[i][1]) {
				ans*=2;
			}
		}
	}
	printf("%lld\n", ans);
	return 0;
}

C. Consonant Fencity

因为不同字符数量很少,故直接状压枚举即可。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/11 14:53:04
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
const int ban[] = {0, 'e' - 'a', 'i' - 'a', 'o' - 'a', 'u' - 'a', 'w' - 'a', 'y' - 'a'};
 
string str;
int cnt[26], mp[26], mp2[26], change[26];
int a[26][26];
 
bool ok(int c) {
    for (int i = 0; i < 7; i++) {
        if (c == ban[i]) {
            return false;
        }
    }
    return true;
}
 
void run() {
    freopen("consonant.in", "r", stdin);
    freopen("consonant.out", "w", stdout);
    cin >> str;
    int n = str.length();
    for (int i = 0; i < n; i++) {
        if (ok(str[i] - 'a')) {
            ++cnt[str[i] - 'a'];
        }
    }
    int tot = 0;
    for (int i = 0; i < 26; i++) {
        if (cnt[i]) {
            mp[i] = tot;
            mp2[tot] = i;
            ++tot;
        }
    }
    if (tot == 0) {
        cout << str << '\n';
        return;   
    }
    for (int i = 0; i < n; i++) {
        if (i + 1 < n) {
            if (ok(str[i] - 'a') && ok(str[i + 1] - 'a')) {
                ++a[mp[str[i] - 'a']][mp[str[i + 1] - 'a']];
                ++a[mp[str[i + 1] - 'a']][mp[str[i] - 'a']];
            }
        }
    }
    //for (int i = 0; i < tot; i++) {
        //for (int j = 0; j < tot; j++) {
            //cout << a[i][j] << ' ';
        //} cout << '\n';
        //cout << mp2[i] << '\n';
    //}
    int ans = 0;
    for (int sta = 0; sta < 1 << (tot - 1); sta++) {
        int res = 0;
        for (int i = 0; i < tot - 1; i++) {
            if (sta >> i & 1) {
                for (int j = 0; j < tot; j++) {
                    if (!(sta >> j & 1)) {
                        res += a[i][j];
                    }
                }
            }
        }
        if (res > ans) {
            ans = res;
            memset(change, 0, sizeof(change));
            for (int i = 0; i < tot; i++) {
                if (sta >> i & 1) {
                    change[mp2[i]] = 1;
                }
            }   
        }
    }
    for (int i = 0; i < n; i++) {
        if (change[str[i] - 'a']) {
            str[i] = str[i] - 'a' + 'A';
        }
    }
    cout << str << '\n';
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

E. Equal Numbers

显然最后每个数只能都变为他们的\(lcm\)或者变到某一个数上面去。
那么对这两种情况都处理一下取最小值即可。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/11 15:57:13
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 3e5 + 5, MAX = 1e6 + 5;
 
int n;
int cnt[MAX];
struct node {
    int c, v;
    bool operator < (const node& A)const {
        return c > A.c;
    }
};
 
int ans1[MAX], ans2[MAX], to[MAX];
 
void solve1(int* ans) {
    int k = n;
    priority_queue <node> q;
    for (int i = 1; i < MAX; i++) if (cnt[i]) {
        q.push(node {cnt[i], i});
    }
    int cur = 0;
    while (!q.empty()) {
        node now = q.top(); q.pop();
        if (k < now.c) break;
        if (to[now.v] == now.v) continue;
        cur += now.c;
        --ans[cur];
        k -= now.c;
    }
}
 
void solve2(int* ans) {
    int k = n;
    priority_queue <node> q;
    for (int i = 1; i < MAX; i++) if (cnt[i]) {
        q.push(node {cnt[i], i});
    }
    int cur = 0;
    while (!q.empty()) {
        node now = q.top(); q.pop();
        if (k < now.c) break;
        cur += now.c;
        if (cur != now.c) --ans[cur];
        k -= now.c;
    }   
}
 
void run() {
    freopen("equal.in", "r", stdin);
    freopen("equal.out", "w", stdout);
    cin >> n;
    for (int i = 1; i <= n; i++) {
        int x; cin >> x;
        ++cnt[x];
    }
    int tot = 0;
    for (int i = 1; i < MAX; i++) if (cnt[i]) {
        ++tot;
        for (int j = i; j < MAX; j += i) {
            if (cnt[j]) {
                to[i] = j;
            }
        }
    }
    solve1(ans1), solve2(ans2);
    ans1[0] += tot, ans2[0] += tot;
    for (int i = 1; i <= n; i++) {
        ans1[i] += ans1[i - 1];
        ans2[i] += ans2[i - 1];
    }
    for (int i = 0; i <= n; i++) {
        int ans = min(ans1[i], ans2[i]);   
        cout << ans << " \n"[i == n];
    }
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

G. Grand Test

题意:
给定\(n\)\(m\)条边的有向图,现在要找到起点\(S\)和终点\(T\),并且满足\(S\rightarrow T\)存在三条除开起点终点之外的点不重复的路径,并且要输出路径。

思路:
画图即可发现,若满足题中条件,一定具有“由两个环拼接起来”的特征,即两个环共享一部分,画个图就比较显然了。
那么找环的问题我们可以在\(dfs\)树或者\(bfs\)树上解决。
对于每条返祖边\((u,v)\),暴力给树上\(u\rightarrow v\)的路径染色。若某条边有两种颜色那么说明存在两个环重合,直接扣出来暴力\(dfs\)找路径即可。
细节见代码:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/12 15:31:13
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
 
int n, m;
vector <pii> G[N], edges;
vector <int> nG[N];
pii color[N], f[N];
int vis[N], dfn, c1, c2;
bool flag;
 
int paint(int x, int c) {
    if (color[x].fi == -1) {
        color[x].fi = c;
        return 0;
    }
    color[x].se = c;
    return 1;
}
 
void paint(int x, int y, int c) {
    while (x != y) {
        pii now = f[x];
        if (paint(now.se, c)) {
            flag = true;
            c1 = color[now.se].fi;
            c2 = color[now.se].se;
        }   
        x = now.fi;
    }
}
 
void dfs(int u, int fa, int t) {
    if (flag) return;
    f[u] = MP(fa, t);
    vis[u] = ++dfn;
    for (auto it : G[u]) {
        int v = it.fi, id = it.se;
        if (v == fa) continue;
        if (!vis[v]) {
            dfs(v, u, id);
        } else if (vis[v] < vis[u]) {
            if (flag) continue;
            paint(u, v, id);
        }
    }
}
 
int d[N];
 
bool ok(int id, int c) {
    return color[id].fi == c || color[id].se == c || id == c;
}
 
void find() {
    for (int i = 1; i <= m; i++) {
        if (ok(i, c1) || ok(i, c2)) {
            int u = edges[i].fi, v = edges[i].se;
            nG[u].push_back(v);
            nG[v].push_back(u);
            ++d[u], ++d[v];
        }
    }
}
 
vector <vector <int>> cyc(3);
int S, T, t;
 
void go(int u, int fa) {
    if (u == T) return;
    for (auto v : nG[u]) if (v != fa) {
        cyc[t].push_back(v);
        go(v, u);
        if (u == S) ++t;
    }
}
 
void run() {
    cin >> n >> m;
    flag = false;
    t = dfn = 0;
    for (int i = 0; i < 3; i++) {
        cyc[i].clear();
    }
    for (int i = 1; i <= n; i++) {
        G[i].clear();
        nG[i].clear();
        vis[i] = d[i] = 0;
    }
    for (int i = 1; i <= m; i++) {
        color[i] = MP(-1, -1);
    }
    edges.clear(), edges.push_back(MP(0, 0));
    for (int i = 1; i <= m; i++) {
        int u, v; cin >> u >> v;
        G[u].push_back(MP(v, i));
        G[v].push_back(MP(u, i));
        edges.push_back(MP(u, v));
    }
    for (int i = 1; i <= n; i++) {
        if (!vis[i]) {
            dfs(i, 0, 0);
        }
    }
    
    if (!flag) {
        cout << -1 << '\n';
        return;
    }
    find();
    S = -1, T = -1;
    for (int i = 1; i <= n; i++) {
        if (d[i] >= 3) {
            if (S == -1) {
                S = i;
            } else if (T == -1) {
                T = i;
            }
        }
    }
    go(S, 0);
    cout << S << ' ' << T << '\n';
    for (int i = 0; i < 3; i++) {
        cout << sz(cyc[i]) + 1 << ' ' << S;
        for (auto it : cyc[i]) {
            cout << ' ' << it;
        }
        cout << '\n';
    }
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    freopen("grand.in", "r", stdin);
    freopen("grand.out", "w", stdout);
    int T; cin >> T; while(T--)
    run();
    return 0;
}

H. Hidden Supervisors

题意:
给定一个森林,现在每棵树两两相邻结点可以匹配,一个结点最多只能匹配一次。
现在将所有树拼接为一颗树,要求怎么拼接,最后的匹配对数最大。

思路:

  • 对于一颗树,显然自底向上进行两两匹配最优。最后一颗树只会剩下0/1个根节点以及若干个叶子结点,接下来考虑不同树的"叶子-根"的匹配。
  • 考虑拼接,直接将剩下\(1\)个根节点的树拼接到前面结点中即可,并且更新树的叶子结点;如果前面没有结点,则直接与树根相连,但此时不会产生新的匹配。
  • 拼接时要按照叶子结点从大到小的顺序进行拼接,这样更新过后的结点数会更多,更有利于后续树根的匹配。

细节见代码:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/11 17:03:22
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
 
int n;
int fa[N];
bool vis[N];
int ans, tot;
vector <int> G[N], t;
vector <pair<vector<int>, int>> a;
 
void dfs(int u) {
    t.push_back(u);
    for (auto v : G[u]) {
        dfs(v);
        if (!vis[u] && !vis[v]) {
            vis[u] = vis[v] = true;
            ++ans;
        }
    }
}
 
void gao(int u) {
    t.clear();
    dfs(u);
    vector <int> tmp = t;
    t.clear();
    for (auto it : tmp) {
        if (!vis[it]) {
            t.push_back(it);
        }
    }
    int f = 0;
    for (int i = 0; i < sz(t); i++) {
        if (fa[t[i]] == 0 && t[i] != 1) {
            swap(t[sz(t) - 1], t[i]);
            f = 1;
            break;
        }
    }
    a.push_back(MP(t, f));
}
 
void run() {
    freopen("hidden.in", "r", stdin);
    freopen("hidden.out", "w", stdout);
    cin >> n;
    for (int i = 2; i <= n; i++) {
        cin >> fa[i];
        if (fa[i] > 0) {
            G[fa[i]].push_back(i);
        }
    }
    for (int i = 1; i <= n; i++) {
        if (fa[i] == 0) {
            gao(i);
        }
    }
    vector <vector <int>> v1;
    vector <int> v0;
    for (auto& it : a) if (sz(it.fi)) {
        if (it.se) v1.push_back(it.fi);
        else {
            for (auto& it2 : it.fi) {
                v0.push_back(it2);
            }
        }
    }
    sort(all(v1), [&] (vector <int> A, vector <int> B) {
        return sz(A) > sz(B);
    });
    for (auto& v : v1) {
        if (sz(v0)) {
            ++ans;
            fa[v[sz(v) - 1]] = v0.back();
            v0.pop_back();
            v.pop_back();
        }
        if (sz(v)) {
            for (auto it : v) {
                v0.push_back(it);
            }
        }
    }
    cout << ans << '\n';
    for (int i = 2; i <= n; i++) {
        if (fa[i] == 0) fa[i] = 1;
        cout << fa[i] << " \n"[i == n];
    }
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

I. Intelligence in Perpendicularia

答案即为总边长减去里面的边长。

Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define TM "intel"
int xs[1007], ys[1007];
 
int main() {
#ifndef LOCAL
	freopen(TM".in", "r", stdin);
	freopen(TM".out", "w", stdout);
#endif
	int n; scanf("%d", &n);
	for(int i=0; i<n; i++) {
		scanf("%d%d", &xs[i], &ys[i]);
		xs[i]+=1000001;
		ys[i]+=1000001;
	}
	int mx,my,Mx,My;
	mx=Mx=xs[0], my=My=ys[0];
	for(int i=0; i<n; i++) mx=min(mx,xs[i]), my=min(my,ys[i]), Mx=max(Mx,xs[i]), My=max(My,ys[i]);
	xs[n]=xs[0], ys[n]=ys[0];
 
	long long ans1=0, ans2=0;
	for(int i=1; i<=n; i++) {
		int x1=xs[i], x2=xs[i-1];
		int y1=ys[i], y2=ys[i-1];
		if(x1==x2) {
			if(y1>y2) swap(y1,y2);
			int v=y2-y1;
			ans2+=v;
		} else {
			if(x1>x2) swap(x1,x2);
			int v=x2-x1;
			ans1+=v;
		}
	}
	ans1 -= (Mx-mx)*2;
	ans2 -= (My-my)*2;
	printf("%lld\n", ans1+ans2);
	return 0;
}

K. Kotlin Island

签到。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/11 13:24:07
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 100 + 5;
 
int r, c, n;
int rows[N], cols[N];
 
void run() {
    freopen("kotlin.in", "r", stdin);
    freopen("kotlin.out", "w", stdout);
    cin >> r >> c >> n;
    int x, y;
    for (int i = 1; 1ll * i * i <= n; i++) {
        if (n % i == 0) {
            x = i - 1, y = n / i - 1;
            if (2 * x + 1 <= r && 2 * y + 1 <= c) {
                break;
            }
            x = n / i - 1, y = i - 1;
            if (2 * x + 1 <= r && 2 * y + 1 <= c) {
                break;
            }           
        }
    }
    if (2 * x + 1 <= r && 2 * y + 1 <= c) {
        for (int i = 2; i <= 2 * x; i += 2) {
            rows[i] = 1;
        }
        for (int i = 2; i <= 2 * y; i += 2) {
            cols[i] = 1;
        }
        for (int i = 1; i <= r; i++) {
            for (int j = 1; j <= c; j++) {
                if (rows[i] || cols[j]) {
                    cout << "#";
                } else cout << ".";
            }
            cout << '\n';
        }
    } else {
        cout << "Impossible" << '\n';
    }
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

L. Little Difference

题意:
给定一个数\(n,n\leq 10^{18}\),将其分为若干个相差至多为\(1\)的数的乘积,如果有无限个则输出\(-1\)

思路:
显然最后的分解式中有\(1\)则有无限多个分解方案,此时只可能出现在\(n=1,n=2\)的情况中。
分解式中有\(1,2\)个数的情况我们可以直接考虑,接下来就处理分解式中有大于\(2\)个数的情况,此时每个数最多为\(10^6\)。那么我们可以直接枚举分解式中较小的那个数即可。
详见代码:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/11 14:13:21
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
 
void run() {
    freopen("little.in", "r", stdin);
    freopen("little.out", "w", stdout);
    ll n; cin >> n;
    ll p = n;
    while (p % 2 == 0) {
        p /= 2;
    }
    if (p == 1) {
        cout << -1 << '\n';
        return;
    }
    
    vector <vector <ll>> ans;
    ans.push_back({n});
    ll t = sqrt(n + 0.5);
    while (t * t > n) --t;
    if (t * t == n) {
        ans.push_back({t, t});
    }
    if (t * (t + 1) == n) {
        ans.push_back({t, t + 1});   
    }
    for (int i = 2; i <= min(n, 1000000ll); i++) {
        if (n % i) continue;
        vector <ll> res;
        res.push_back(i);
        ll x = n / i;
        while (x % i == 0) {
            x /= i;
            res.push_back(i);
        }
        if (x == 1) {
            ans.push_back(res);
            continue;
        }
        ll x2 = x;
        if (x % (i + 1) == 0) {
            while (x % (i + 1) == 0) {
                x /= (i + 1);
            }
            if (x == 1) {
                x = x2;
                while (x % (i + 1) == 0) {
                    x /= (i + 1);
                    res.push_back(i + 1);
                }
                sort(all(res));
                ans.push_back(res);
            }
        }
    }
    vector <vector<ll>> result;
    sort(all(ans));
    result.push_back(ans[0]);
    for (int i = 1; i < sz(ans); i++) {
        if (ans[i] != ans[i - 1]) {
            result.push_back(ans[i]);
        }
    }
    cout << sz(result) << '\n';
    for (auto seq : result) {
        cout << sz(seq);
        for (auto it : seq) {
            cout << ' ' << it;
        }
        cout << '\n';   
    }
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}
posted @ 2020-06-16 21:15  heyuhhh  阅读(406)  评论(0编辑  收藏  举报