考砸了。。。
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。