qbxt国庆水题记day6
来源:互联网 发布:定性与定量数据区别 编辑:程序博客网 时间:2024/05/13 19:41
qbxt国庆水题记
day6
//40 + 20 + 10 = 70
//除了自己垃圾不想说什么了
Problem A. 最佳进制
File: divisors.*
Time limit: 1s
Memory limit: 256MB
如今我们最常用的是十进制,据说这是因为人有十根十指。
但事实上这并不是十分方便,10 只有四个因为 1、2、5、10,像
1 1
- -
3 6
这些分数在十进制下的小数表示就
不是很优美。在这种要求下,12、24 甚至 60 进制会更好一些。
现在想求出不超过 n 的最佳进制数,也就是拥有最多的因子。
Input
第⼀⾏包含⼀个整数 n,(1 ≤ n ≤ 10 16 )。
Output
输出⼀个数 c,表⽰最佳进制数。
Examples
Input Output
100
Subtasks、
60
对于 20% 的数据,n ≤ 100。
对于 40% 的数据,n ≤ 10e5 。
对于 60% 的数据,n ≤ 10e9 。
对于 100% 的数据,k ≤ 10e16 。
根据质因数分解
因数个数 :(a1 +1)*(a2+1)*.....*(an+1)
暴力即可找到n以前拥有最大因数个数的数
//来自[SDOI2005]反素数ant(扩大范围版)
//找了半天规律想错了
#include<iostream>#include<cstdio>using namespace std;#define ll long longll n;int a[100] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41};ll maxn = 1, ans = 1;void dfs(int x,ll sum,ll p,int num) { if( p > ans || ( p == ans && maxn > sum) ) { ans = p; maxn = sum; } if(x > 13) return; for(int i = 1; i <= num; i++) { if(sum * a[x] > n) break; dfs(x + 1,sum *= a[x],p * (i + 1), i); }}int main() { freopen("divisors.in","r",stdin); freopen("divisors.out","w",stdout); cin>>n; dfs(1,1,1,100); cout<<maxn; return 0;}
Problem B. 树
File: tree.*
Time limit: 1s
Memory limit: 256MB
给出一棵节点数为 n 的有根树,现在需要给每个节点标号,要求对应子树同构的节点标号相同。
若图 G 1 ,G 2 同构,则存在 G 1 点集和 G 2 点集之间的双射 ϕ,满足u → v 是 G 1 中的一条边当且仅当ϕ(u) → ϕ(v) 是 G 2 中的一条边。
Input
第⼀⾏包含⼀个数 n(1 ≤ n ≤ 10 5 ),表子树的点数。
第⼆⾏包含 n − 1 个数,第 i 个数表⽰编号为 i + 1 点的⽗节点编号,满⾜⽗节点的编号⼩于⼦节点,根
节点编号为 1。
Output
包含 n 个数,表⽰节点标号,标号⼤⼩范围在 1 到 n 之间。如果有多种标号,给出字典序最⼩的标
号。
Examples
Input Output
9
1 2 2 1 5 5 7 7
Subtasks
1 2 3 3 4 3 2 3 3
对于 30% 的数据,n ≤ 12。
对于 50% 的数据,n ≤ 100。
对于 100% 的数据,n ≤ 10e5 。
树上Hash(这是什么鬼)
对于每个节点,统计每个儿子的hash值
对哈希值排序,得到此节点的值
暴力递归对拥有不同哈希值的点进行染色
map暴力判断
#include<iostream>#include<cstdio>#include<cstring>#include<map>#include<algorithm>#include<vector>using namespace std;const int maxn = 100000 + 100;int n,fa[maxn];struct edge{ int u,v; int next;}e[maxn];int head[maxn],tot = 0,vis[maxn],dis[maxn];int read() { int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f;}map < vector<int>, int> q;void add(int u, int v ) { e[++tot] = (edge) {u,v,head[u]}; head[u] = tot;}int dfs(int x) { vector <int> tp; for(int i = head[x]; i; i = e[i].next) { int v = e[i].v; tp.push_back(dfs(v)); } sort(tp.begin(),tp.end()); if(!q[tp]) q[tp] = ++tot; vis[x] = q[tp]; return vis[x];}int main() { freopen("tree.in","r",stdin); freopen("tree.out","w",stdout); n = read(); for(int i = 2; i <= n; i++) { fa[i] = read(); add(fa[i],i); } tot = 0; dfs(1); tot = 0; for(int i = 1; i <= n; i++) { if(dis[vis[i]] == 0) { dis[vis[i]] = ++tot; } cout<<dis[vis[i]]<<' '; } return 0;}
Hash表版
#include<iostream>#include<cstdio>#include<cstring>#include<map>#include<algorithm>using namespace std;#define ll long longconst int maxn = 100000 + 100;const int mod = 1000000007;const int base = 100000;int n;struct edge{ int u,v; int next;}e[maxn];int head[maxn],tot = 0,vis[maxn],dis[maxn];int read() { int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f;}void add(int u, int v ) { e[++tot] = (edge) {u,v,head[u]}; head[u] = tot;}map<int, int> q;int dfs(int x) { int a[1001]; memset(a,0,sizeof(a)); int o = 0; for(int i = head[x]; i; i = e[i].next) { int v = e[i].v; a[++o] = dfs(v); } sort(a + 1, a + o + 1); int tp = 1; for(int i = 1; i <= o; i++) { tp = ( (tp * base) % mod + a[i] ) % mod; } if(!q[tp]) q[tp] = ++tot; vis[x] = q[tp]; return vis[x];}int main() { freopen("tree.in","r",stdin); freopen("tree.out","w",stdout); n = read(); for(int i = 2; i <= n; i++) { int l = read(); add(l,i); } tot = 0; dfs(1); tot = 0; for(int i = 1; i <= n; i++) { if(!dis[vis[i]]) { dis[vis[i]] = ++tot; } cout<<dis[vis[i]]<<' '; } return 0;}
Problem C. 关系
File: relations.*
Time limit: 1s
Memory limit: 256MB
有一个二元关系 R,R 可以被表示成 n ∗ n 的布尔数组。
现在希望找到长度都为 n 的数组 f 和 g,要求满足 R x,y = 1 当且仅当 f(x) ≤ g(y)。
Input
第一行包含一个整数 n(1 ≤ n ≤ 1000),表⽰数组的大小。
接下来的 n 行表示二元关系 R。
Output
第⼀⾏输出能否找到数组 f 和 g,如果能找到输出 YES,否则输出 NO。−10 9 ≤ f i ,g i ≤ 10 9
第⼆⾏输出 n 个整数,表⽰数组 f。
第三⾏输出 n 个整数,表⽰数组 g 。
Examples
Input Output
3
111
110
100
Subtasks
YES
0 1 2
2 1 0
对于 20% 的数据,n ≤ 10。
对于 50% 的数据,n ≤ 100。
对于 100% 的数据,n ≤ 1000。
可以发现
当R(i,j )= 1时 f[i] <= g[i]
当R(i,j )= 0时 f[i] > g[i]
所以可以建图来解决
定义 u -> v 为 f[u] < g[v]
根据拓扑排序,得到拓扑序,f,g数组就可以用拓扑序来表示
对于NO,找环即可
#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;#define ll long longconst int maxn = 10000 + 100;int n;char a[maxn];struct edge { int u,v; int next;}e[maxn];int head[maxn], tot = 0, dis[maxn],val[maxn];void add(int u, int v) { e[++tot] = (edge){u,v,head[u]}; head[u] = tot; dis[v]++;}void topo() { queue<int>q; for(int i = 1; i <= n * 2; i++) if(!dis[i]) q.push(i); while(!q.empty()) { int k = q.front(); q.pop(); for(int i = head[k]; i; i = e[i].next) { int v = e[i].v; val[v] = max(val[v],val[k] + 1); dis[v]--; if(!dis[v]) q.push(v); } }}int main() { freopen("relations.in","r",stdin); freopen("relations.out","w",stdout); cin>>n; for(int i = 1; i <= n; i++) { cin>>a; for(int j = 1; j <= n; j++) { if(a[j - 1] == '0') add(i,j + n); else add(j + n,i); } } topo(); for(int i = 1; i <= n * 2; i++) if(dis[i]) { cout<<"NO"<<endl; return 0; } cout<<"YES"<<endl; for(int i = 1; i <= n; i++) cout<<val[i]<<' '; cout<<endl; for(int i = 1; i <= n; i++) cout<<val[i + n]<<' '; cout<<endl; return 0;}
- qbxt国庆水题记day6
- qbxt国庆水题记day1
- qbxt国庆水题记day2
- qbxt国庆水题记day3
- qbxt国庆水题记day4
- qbxt国庆水题记day5
- qbxt day6
- [qbxt考试Day6]小学数学 + Hash
- 【泉州一中国庆集训day6】String
- 国庆清北刷题冲刺班 Day6 上午
- 国庆清北刷题冲刺班 Day6 下午
- QBXT
- day6
- Day6
- day6
- DAY6
- Day6
- DAY6
- LintCode—贪心—落单的数
- Socket编程
- JS异步操作-promise
- Linux SSH 无密码登录
- 1.2.3实例变量与线程安全(共享数据的情况)
- qbxt国庆水题记day6
- 在applicationContext.xml中引入jdbc.properties文件
- 【noip2016提高组day2T3】【愤怒的小鸟】状压dp转移时的集合包含
- nginx的配置文件详解
- 八皇后问题
- Linux 基础操作 (四)————查看用户信息及修改、提权、修改密码
- 第二次作业,模拟sim卡与手机
- javascript 观察者模式 (订阅者与发布者)
- C语言的“隐式函数声明”违背了 “前置声明” 原则