清北學堂 2017 10 06

2021-08-09 01:19:02 字數 4345 閱讀 8194

****

因為是剛聽完課所以想把思路記下來,有一些其實也是一知半解的,如果有dalao可以幫忙講解那真是再感謝不過了。

*****還有為什麼我畫圖這麼醜,哇的一下哭出聲*******

problem a. 最佳進製

如今我們最常用的是十進位制,據說這是因為人有十根手指。

但事實上這並不是十分方便,10 只有四個因子 1、2、5、10,

像 1/3、1/6 這些分數在十進位制下的十數表示就

不是很優美。在這種要求下,12、24 甚至60 進製會更好一些。

現在想求出不超過 n 的最佳進製數,也就是擁有最多的因子。

input

第一包含乙個整數 n,(1 ≤ n ≤ 1e16)。

output

輸出乙個數 c,表示最佳進製數。

examples

input

100

output

60subtasks

對於20% 的資料,n<=100。

對於40% 的資料,n<=1e5。

對於60% 的資料,n<=1e9。

對於100% 的資料,k<=1e6。

注:若有多個解,輸出最小的那個

解析:求因子最多的數

乙個大多數人都知道但我不知道的關係:x=∏pi^ai //∏為累乘符號

即x為多個質因數(pi)的ai次方的乘積

則這個數所有的因子個數ans=∏(ai+1)

例:12=(2^2)*(3^1)

還有就是如果ai是x的因子,則a1~a(i-1)一定都為x的因子(這裡不是很能理解,如果這個數是質數咋辦???求告知) 即a1>=a2>=a3….>=an

由於題目範圍為1e16,且2*3*5*……*47>1e16,則分解因數只需到47

另外就是如果x|y,則x的每個質因數一定也為y的質因數,且冪次一定比在y的冪次小

又因為(2^3)*(3^2)與(2^2)*(3^3)的因子數是一樣的,因此最好讓小的質因子的冪次更高

下面就是愉快的**時間了

#include 

#include

#include

#include

using namespace std;

long long n, maxd, ans;

int prime = ;

void dfs(int x, long long sum, long long nowd, long long limit)

int main()

problem b. 樹

file: tree.*

time limit: 1s

memory limit: 256mb

給出一棵節點數為n 的有根樹,現在需要給每個節點標號,要求對應子樹同構的節點標號相同。

若圖g1,g2 同構,則存在g1 點集和g2 點集之間的雙射ϕ,滿足u ->v 是g1 中的一條邊當且僅當

ϕ(u) ! ϕ(v) 是g2 中的一條邊。

input

第一包含乙個數n(1<=n<=105),表示樹的點數。

第二行包含n - 1 個數,第i 個數表示編號為i + 1 點的父節點編號,滿足父節點的編號小於子節點,根

節點編號為1。

output

一行包含n 個數,表示節點標號,標號大小範圍在1 到n 之間。如果有多種標號,給出字典序最小的標

號。examples

input

91 2 2 1 5 5 7 7

output

1 2 3 3 4 3 2 3 3

subtasks

對於30% 的資料,n<=12。

對於50% 的資料,n<=100。

對於100% 的資料,n<=105。

解析:一道」簡單的」hash題

先說一下啥叫同構:即子樹的節點和構成相同(即相對位置相同)

在下圖中,4/5/7/8/9全為葉子結點,則他們位置相同;2/6都各有兩個子節點,則它們位置相同;而1/3的子節點各不相同,應處於不同的位置(位置也即最後要求的節點編號)

另外,子樹是可以旋轉的,也就是說下面的這兩棵樹也是同構的

下面就開始hash了

由於是否同構看到是子樹,因此我們從葉子到根hash,hash值相同的則為同構

在上圖中,令4/7/8/9/10/11都為空集,也就是[ ],則5/6均為[1,1],2/3為[1,2]/[2,1](一樣的),1為[3,3].

hash完可以發現4/7/8/9/10/11的值是一樣的,5/6的值一樣,2/3的值一樣,1自己乙個值

具體如何hash呢?即將每個數看成n進製的,然後將它們化為10進製,例n進製下的12為10進製下的1*n+2

當所有節點的hash值都求完後,我們設乙個計數器cnt,每當出現乙個新數,就cnt++,然後把cnt作為標號賦給當前值,若此hash值之前已經出現,則直接輸出

具體實現可用map函式,怎麼寫在**裡就不多說了

#include 

#include

#include

#include

#include

#include

using namespace std; const int n = 120000; vector

e[n]; map

, int> id; int ans[n], p[n], vis[n]; int n, cnt; int work(int x) sort(u.begin(), u.end()); if (!id[u]) id[u] = ++cnt; ans[x] = id[u]; return ans[x];//返回x的hash值 } int main() work(1); cnt = 0; for(int i = 1; i <= n; i++) ans[i] = vis[ans[i]]; } for(int i = 1; i <= n; i++) printf("%d ", ans[i]); puts(""); }

problem c. 關係

file: relations.*

time limit: 1s

memory limit: 256mb

有乙個二元關係r,r 可以被表示成n*n 的布林陣列。

現在希望找到長度都為n 的陣列f 和g,要求滿足rx,y = 1 當且僅當f(x)<=g(y)。

input

第一行包含乙個整數n(1<=n<=1000),表示陣列的大小。

接下來的n 行表示二元關係r。

output

第一行輸出能否找到陣列f 和g,如果能找到輸出yes,否則輸出no。-1e9<=fi; gi<=109

第二行輸出n 個整數,表示陣列f。

第三行輸出n 個整數,表示陣列g 。

examples

input

3111

110100

output

yes0 1 2

2 1 0

subtasks

對於20% 的資料,n<=10。

對於50% 的資料,n<=100。

對於100% 的資料,n<=1000。

解析:zcc dalao說看到這個就應該想到圖啊(我沒想到但我記住了)

如果a<=b,b<=c,則一定有a<=c

即r[a][b]=1,r[b][c]=1--->>r[a][c]=1若不滿足此條件則輸出」no」

我們另r[a][b]=1當且僅當f[a]>g[b]時(為了建圖方便)

如果r[x][y]=1,則連一條x到y+n(為了方便輸出)

同理,如果r[x][y]=0,則連一條x到y+n

則可得到乙個dag(有向無環圖)[因為a

之後就拓撲排序求值啦(第幾個拿到則為幾)

**

#include 

#include

#include

#include

#include

#include

using namespace std; int f[1005], g[1005], cnt[1005], n; int cmp(int i, int j) int main() if(!correct) break; } for(int i=0; i

清北學堂 2017 10 01

problem 1.alien input file alien.in output file alien.out time limit 1s memory limit 128m 小y 最近正在接受來自x3 星球的外星人的採訪。在那個星球上,每個人的名字都是乙個正整數。所有在這個星球上的居民都是相互...

清北學堂 Pa

pa 題目描述 漢諾塔公升級了 現在我們有?個圓盤和?個柱子,每個圓盤大小都不一樣,大的圓盤不能放在小的圓盤上面,個柱子從左到右排成一排。每次你可以將一 個柱子上的最上面的圓盤移動到右邊或者左邊的柱子上 如果移動之後是合法的 話 現在告訴你初始時的狀態,你希望用最少的步數將第?大的盤子移動到第?根 ...

清北學堂 死亡(death)

m個位置可以打sif,n 1個人等著打sif,已知前n個人的時間,問第n 1個人什麼時候才能打sif 不能插隊,即必須按順序來打sif 輸入n,m以及每個人所需要的時間 輸出第n 1個人所需的時間 用優先佇列用優先佇列用優先佇列 佇列用來存每個水龍頭所需要的總時間,到了最後用了最少時間的水龍頭就是第...