考砸了。。。
T1:20分
T2:10分
T3:0分
總分:30分
回頭補題面和題解
T1:四維世界
Description
衆所周知,我們常感受的世界是三維的。
Polycarp突然對四維空間產生了興趣,他想對四維空間進行一些研究。但是在此之前,他必須先對三維世界瞭解透徹。
於是Polycarp決定從零維,也就是一個點,開始他的研究。我們把一個點放在三維空間中,Polycarp把這個點視爲原點,並確定了三個正方向。他可以把這個點往三個方向之一拉伸一個單位,那麼這個點就變爲了一維的一條長度爲一的線段。然後如果他把這條線段往另一方向拉伸一個單位,那麼這條線就變爲了二維的一個矩形。如果繼續拉伸可能就會進入三維世界,也就是變爲直四棱柱。
Polycarp認爲矩形、線段甚至點都可以看作某一維或某幾維爲豐的直四棱柱。
現在Polycarp想演示把一個點一步一步拉伸爲邊長爲n的正六面體的過程,但他缺失了m種形態的直四棱柱模具(Polycarp擁有其他的所有直四棱柱模具),他想知道共有多少種演示方案。
Polycarp的演示過程需要每拉伸一個單位時對應形態的直四棱柱。
因爲方案數很大,所以輸出答案對10^9+7的結果。
Input
從文件poly.in中讀入數據。
第一行兩個整數n;m,分別表示直四棱柱的邊長和他缺失的模具數量。
接下來m行,第i行三個整數x; y; z,表示第i個缺失模具的長、寬、高。
Output
輸出到文件poly.out中
一個整數,即答案。
Sample Input
2 3
1 0 1
1 1 1
0 2 0
Sample Output
36
Data Constraint
1 n<=7 m<=100
2 n<=300 m<=5000
3 n<=5000 m<=5000
4 n<=100000 m=0
5 n<=100000 m<=5000
題解:
首先從(0,0,0)到(x,x,x)的方案數爲C(3x,x)*C(2x,x)
(共3x步,選擇x步在x方向,再選擇x步在y方向)
將障礙點排序,按順序遞推,如果有限制,就減去經過從上一個障礙點到這個點的方案數。
求組合數的時候需要用逆元,預處理一下就好了
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
#define ll long long
#define MM 300010
int xx;int ff;char ch;
inline int read(){
ff=1;xx=0;ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')ff=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
xx=(xx<<1)+(xx<<3)+ch-'0';
ch=getchar();
}
return xx*ff;
}
#define MOD 1000000007
ll f[MM];
struct node{
int x,y,z;
}a[MM];
int n;int m;
bool cmp(node x,node y){
if(x.x!=y.x)return x.x<y.x;
if(x.y!=y.y)return x.y<y.y;
return x.z<y.z;
}
ll g[MM];
ll h[MM];
inline ll ksm(ll a,ll k){
ll base =a ;
ll ans=1;
for(;k;k>>=1){
if(k&1)ans=(ans*base)%MOD;
base = (base *base )%MOD;
}
return ans;
}
int main(){
freopen("poly.in","r",stdin);
freopen("poly.out","w",stdout);
memset(f,0,sizeof(f));
n=read();m=read();
for(int i=1;i<=m;++i){
a[i].x=read();
a[i].y=read();
a[i].z=read();
}
sort(a+1,a+1+m,cmp);
g[0]=h[0]=1;
int n3=n*3;
for(int i=1;i<=n3;++i)g[i]=(g[i-1]*i)%MOD;
if(m==0){
printf("%lld\n",(g[n3]*ksm((g[n]*g[n]%MOD*g[n]%MOD)%MOD,MOD-2))%MOD);
return 0;
}
++m;
a[m].x=n;
a[m].y=n;
a[m].z=n;
h[n]=ksm(g[n],MOD-2);
for(int i=n-1;i>0;--i)h[i]=(h[i+1]*(i+1))%MOD;
for(int i=1;i<=m;++i){
f[i]=(((((g[a[i].x+a[i].y+a[i].z]*h[a[i].x])%MOD)*h[a[i].y])%MOD)*h[a[i].z])%MOD;
for(int j=1;j<i;++j){
if(a[i].x>=a[j].x&&a[i].y>=a[j].y&&a[i].z>=a[j].z){
f[i]=(f[i]-f[j]*((((((g[a[i].x+a[i].y+a[i].z-a[j].x-a[j].y-a[j].z]*h[a[i].x-a[j].x])%MOD)*h[a[i].y-a[j].y])%MOD)*h[a[i].z-a[j].z])%MOD)+MOD)%MOD;
}
}
}
printf("%lld\n",f[m]);
fclose(stdin);fclose(stdout);
return 0;
}
誒,明明這麼簡單我卻只有20分。。。。不知如何是好,紀念中學的題還是太難了?出征大會讓我們降降難度。。
也許信心賽也是有好處的吧。。
T2 DuLiu
Description
LF是毒瘤出題人中AK IOI2019,不屑於參加NOI的唯一的人。他對人說話,總是滿口垃圾題目者也,教人半懂不懂的。因爲他姓李,別人便從QQ羣上的“毒瘤李Fee”這半懂不懂的話裏,替他取下一個綽號,叫做李Fee。
李Fee一到機房,所有做題的人便都看着他笑,有的叫道,“李Fee,你又來出毒瘤題了!”他不回答,對驗題人說,“我又出了兩道題,給我驗驗。”便排出一排毒瘤題。大家又故意的高聲嚷道,“你又暴露奸商本性拿毒瘤題騙錢剝削驗題人了!”李Fee睜大眼睛說,“你怎麼這樣憑空污人清白……”“什麼清白?我前天親眼見你出了道毒瘤騙錢題,被PTY把std吊着打。” 李Fee便漲紅了臉,額上的青筋條條綻出,爭辯道,“出題人的題不能算騙……毒瘤!……出題人的題,能算毒瘤騙錢題麼?”接連便是難懂的話,什麼“多叉splay隨機點分治”,什麼“樹鏈剖分套分治FFT”之類,引得衆人都鬨笑起來:機房內外充滿了快活的空氣。
雖然他的題十分毒瘤,但他的題還總是有買家。李Fee現在有N道毒瘤題,想將這些題出成一組題來騙大錢。然而顯而易見的是,一組題的毒瘤程度不僅和每道題的毒瘤程度有關,也跟它們的排列順序有關,李Fee需要將它們排列成最毒瘤但又最能騙錢的那個順序。
具體來說,這N道題每題都有一個毒瘤值,它們構成了一個序列。李Fee心目中有一個理想的毒瘤值序列,這個序列並不一定每一題的毒瘤值都是原本N道題中出現的,所以李Fee準備進行一些改動。這些改動體現在毒瘤值上就是將某道題的毒瘤值改爲所有題的毒瘤值的二進制異或值。但是,改動題目是很麻煩的,他想算出最少需要多少次改動才能將原本的毒瘤值序列改成理想的毒瘤值序列,李Fee忙於出毒瘤題,他想請發明O(1/n)算法用暴力搜過所有毒瘤題的你幫他算出答案。但是他是個奸商,所以他並不打算給你報酬。
Input
第一行1個正整數N,如題目所示。
第二行N個非負整數,表示初始的題目毒瘤值序列
第三行N個非負整數,表示理想的題目毒瘤值序列
Output
單獨一行,一個整數,表示最少需要多少次改動
如果怎麼改動都無法改成理想的毒瘤值序列,說明這組題出的相當失敗,請輸出-1
Sample Input
3
0 1 2
3 1 0
Sample Output
2
樣例解釋:
第一次,整個序列異或爲3,把第一個數0換成3,序列變成3,1,2
第二次,整個序列異或爲0,把第三個數2換成0,序列變成3,1,0
Data Constraint
對於10%的數據,1<=N<=5
對於30%的數據,1<=N<=10
另有20%的數據,毒瘤值爲0或1
對於100%的數據,1<=N<=100000 毒瘤值<2^30
Hint
不要被事物的表面現象所迷惑
題解
一眼看出來是n+1個數通過交換回到原序列的最小次數。。於是華麗麗地寫掛了暴力和正解。。
先判斷無解:
把a序列和b序列的異或和加到序列尾部,排個序看看兩個序列是不是完全相等。
而後用map離散化掉a與b,同一個i,a[i]與b[i]不同的話,就連一條邊(爲什麼這麼做?這樣的話,走過這條邊就等於交換了a[i]與b[i]的位置,從別的數就可以通過b[i]走到a[i]了)。答案爲 總邊數+聯通塊數目-1
如果n+1是自己一個聯通塊,那答案還要再加一,因爲n+1要跳進序列裏面去,有1的花費
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<map>
using namespace std;
#define ll long long
#define MM 100010
int xx;int ff;char ch;
inline int read(){
ff=1;xx=0;ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')ff=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
xx=(xx<<1)+(xx<<3)+ch-'0';
ch=getchar();
}
return xx*ff;
}
struct edge{
int v,nex;
}e1[MM<<1];
int head[MM],len=0;
inline void adde(int u,int v){
e1[++len].v=v;
e1[len].nex=head[u];
head[u]=len;
}
bool vis[MM];
void dfs(int u){
vis[u]=1;
for(int ee=head[u];ee;ee=e1[ee].nex){
int v=e1[ee].v;
if(vis[v])continue;
dfs(v);
}
}
int n;
int a[MM];
int b[MM];
int s[MM];
int t[MM];
int cnt=0;
map <int, int> d;
int main(){
freopen("duliu.in","r",stdin);
freopen("duliu.out","w",stdout);
memset(vis,0,sizeof(vis));
n=read();
for(int i=1;i<=n;++i){
a[i]=read();
s[i]=a[i];
if(!d[a[i]])d[a[i]]=++cnt;
a[n+1]^=a[i];
}
s[n+1]=a[n+1];
if(!d[a[n+1]])d[a[n+1]]=++cnt;
for(int i=1;i<=n;++i){
b[i]=read();
t[i]=b[i];
if(!d[b[i]])d[b[i]]=++cnt;
b[n+1]^=b[i];
}
t[n+1]=b[n+1];
if(!d[b[n+1]])d[b[n+1]]=++cnt;
sort(s+1,s+2+n);
sort(t+1,t+2+n);
for(int i=1;i<=n;++i){
if(s[i]!=t[i]){
//cerr<<s[i]<<" "<<t[i]<<endl;
printf("-1\n");
return 0;
}
}
int n2=n+1;
int ans=0;
for(int i=1;i<=n;++i){
a[i]=d[a[i]];b[i]=d[b[i]];
if(a[i]!=b[i]){
adde(a[i],b[i]);
++ans;
//cerr<<"Q"<<endl;
}
}
a[n+1]=d[a[n+1]];b[n+1]=d[b[n+1]];
if(a[n+1]!=b[n+1]){
adde(a[n2],b[n2]);
}
for(int i=1;i<cnt;++i){
if(!vis[i]&&head[i]){
++ans;
dfs(i);
}
}
--ans;
if(!vis[cnt])++ans;
printf("%d\n",ans);
fclose(stdin);fclose(stdout);
return 0;
}
T3 Travel
Description
EZ同學家裏非常富有,但又極其的謙虛,說話又好聽,是個不可多得的人才。
EZ常常在假期環遊世界,他準備去N(N<=100000)個國家之多,一些國家有航線連接,由於EZ同學有一定的強迫症,任意兩個國家之間都能通過航路直接或間接到達,並且這樣的路徑僅有一種。(簡單來說,這些國家構成了一棵樹)
由於EZ是C國人,因此將C國(1號國家)作爲整棵樹的根
每個國家有一個旅遊熱度A[i]和影響力D[i]。由於目的地有點多,爲了避免選擇困難症,他給每個國家設置了一個嚮往值F[i],它等於所有的A[j]之和,滿足i國在j國向C國走D[j]步的路徑上(經過一條航路算一步,i=j也會被統計,如果D[j]步超過了C國,則超出部分不用管)。
LYD同學家裏有礦,富有程度與EZ不相上下,但他卻在宅與現充間搖擺不定。某次機緣巧合,EZ外出旅遊刺激了LYD,他決定也要開始旅遊。爲了避免又被判高重複率導致被取消資格,他將EZ的旅遊地圖略微做了一點調整,每條航路將有一定的概率出現。
現在他有Q個詢問,每次詢問某個國家所在的聯通塊(由於每條邊是一定概率出現,因此它所在的聯通塊可以是很多種)中所有國家的F[i]值的和的平方的期望(對998244353取模),以此來決定他旅遊的目的地。但他極其厭惡繁瑣的計算,於是他找到了能算出圓周率並將它倒背下來的你,答應給你豐厚的報酬。家裏沒礦,老爸也不是X達集團老總的你決定接受他的任務。
Input
第一行1個正整數N,表示國家數。
接下來N行,第i行兩個非負整數A[i],D[i],表示國家i的旅遊熱度以及影響力
接下來N-1行,每行三個非負整數x,y,v,x,y爲這條航路連接的兩個國家,v爲這條航路出現的概率。(注意每個在EZ的地圖中是沒有出現概率的說法的,因此每個國家的F值與邊的出現概率無關)
接下來一行一個正整數Q,表示詢問數
接下來Q行,每行一個正整數x,表示詢問國家x所在的聯通塊中所有國家的F[i]值的和的平方的期望(對998244353取模)。
Output
Q行,每行一個非負整數表示這次詢問的答案。
Sample Input
Sample Input1:
5
2 1
1 0
3 1
3 2
1 4
1 2 1
1 3 1
2 4 1
2 5 0
3
1
3
5
Sample Input2:
4
5 1
3 0
10 2
4 1
1 2 74017368
1 3 59531864
2 4 25036401
3
4
2
3
Sample Output
Sample Output1:
400
400
1
樣例解釋:
可算出各國的F值分別爲9,5,3,3,1
1,2,3,4必定在同一個聯通塊中,5在另一個聯通塊
1,2,3,4所在聯通塊F值和爲20,因此答案是400
5所在的聯通塊F值和爲1,因此答案是1
Sample Output2:
988451137
606447316
733454972
樣例解釋:
可算出各國的F值分別爲15,7,10,4
根據期望的定義,可計算出答案
Data Constraint
對於100%的數據,1<=N,Q<=2000000<=A[i],v<998244353,0<=D[i]<N
Hint
題目中所有概率、期塑均由這種形式表示或者輸出:
假設這個值爲P/Q,那麼用來表示的是P* Q^(-1) mod 998244353,其中Q^(-1)爲Q在模998244353下的逆元,保證這樣的逆元一定存在)
期望的定義:期望爲每種情況的答案乘上這種情況的概率的總和,你可以理解爲各種情況的加權平均數。
題解
樹形概率DP。