****
因為是剛聽完課所以想把思路記下來,有一些其實也是一知半解的,如果有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個人所需的時間 用優先佇列用優先佇列用優先佇列 佇列用來存每個水龍頭所需要的總時間,到了最後用了最少時間的水龍頭就是第...