【20171018校内模拟赛】
2017-10-18 21:14
363 查看
评测机效率约为4e8,开启O2优化,开大栈空间,T1 时限1s,T2/3 时限均为 2s,内存限制为128MB。
小Z厌恶数学,他决定将数学课本切成一块一块的。他的课本是一个n*m的矩形,小Z决定切K刀,每刀他可以横着切或者竖着切,但是切成的矩形的长和宽都必须是整数。当然,小Z不会做出两次相同的操作。
不巧的是,小Z的数学老师知道了他这个行为,并且刁钻的老师肯定会找到切出的矩形中面积最小的那一块来D他,所以小Z想知道最优情况下面积最小的那一块面积最大能是多少?
输入数据只包含一行三个整数n,m,k,含义如题目所述。
输出一个数字,表示答案。如果没有合法的方案,输出-1。
6 4 2
8
Subtask1 (20 points) 满足 \(n,m \leq 10\)
Subtask2 (20 points) 满足\(n,m \leq 5000\)
Subtask3 (20 points) 满足\(n,m \leq 10^7\)
Subtask4 (40 points) 满足\(n,m \leq 10^9\)
可以简单的证明出,如果切割次数允许只在同一个方向切,肯定是最优的,
否则,肯定是将长边切满之后再切短边最优,因此只需要使得切的边最小的尽可能大,所以要尽量等分,最后计算一下答案就好了。
时空复杂度均为\(O(1)\)
小Z最喜欢数组了,现在他得到了由n个正整数组成的数组ai,他想构造一个相同大小的正整数数组bi满足两个数组的差异度\(\Sigma |ai -bi|\)最小。特殊的是,bi数组的所有元素必须满足两两互质。
第一行一个数n,表示数组大小。
接下来一行n个正整数ai,表示给定的数组。
输出一行n个正整数bi,表示答案。
输出的数字必须满足\(1 \leq bi \leq 10^9\)。如果有多个答案,你可以输出任意一个。
5
1 6 4 2 8
1 5 4 1 9
Subtask1 (20points) 满足$ n \leq 8 , 1 \leq ai \leq 5$
Subtask2 (30points) 满足$ n \leq 50 , 1 \leq ai \leq 15$
Subtask3 (50points) 满足$ n \leq 100 , 1 \leq ai \leq 30$
容易发现\(1 \leq bi \leq 58\),如果\(bi>58\) 可以证明用1替代是等价或更优的,显然,58以内的所有质数只能在整个序列中作为最多一个数的质因子出现,经计算的,58以内的质数个数为16个,故所有质数的状态只有\(2^{16}\)种情况,考虑状态压缩,预处理出1~58中每个数所拥有的质因子集合,使用状态压缩DP即可通过。状态转移方程为:\[f[i][S|set[j]]=f[i-1][S]+|ai-j|(1 \leq j \leq 58 \vee set[j]\cap S = \phi )\]
其中\(set[j]\)表示j含有的质因数集合,\(f[i][S]\)表示前i个位置,质因数状态为S的最优答案。
总复杂度为\(O(58n*2^{16})/O(n*2^{16})\)。
L国包含n个城市和m条双向道路,第i条道路连接ui,vi两个城市,距离为ti,这些道路将所有n个城市连接在一起。明年,L国将会在首都,也就是1号城市举办一年一度的noi,所以L国的国王委托小Z新建一些道路来减少一些城市到达首都的距离。小Z很快修好了道路,但是他却不是很满意。他想知道最多可以少新建多少道路,满足首都到所有城市的最短路长度和现在相同。
第一行读入三个数字n,m,k,依次表示城市的数量,原有道路的数量和新建道路的数量。
接下来m行,每行三个数字ui,vi,ti,表示一条原有的道路
最后k行,每行两个数字si,wi,表示一条新建的道路连接1和si,距离为wi。
输出一个整数,表示最多能少修建多少条新建的道路。
3 2 2
1 2 1
2 3 1
2 2
3 1
1
对于20%的数据,满足\(n,m,k \leq 100\);
另有20%的数据,满足\(k \leq 4\)
对于100%的数据,满足\(n,k \leq 50000 , m \leq 200000 , 1 \leq ti,wi \leq 10^9 si \geq 2\)
考虑一条新建的边一定会被修建的原因,显然是因为2个原因:
1.从1号点到这条边的另一端的最短路被修改了
2.最短路一定包含新的修建的边
考虑如何维护上述两种情况,显然,只需要求一次原先的最短路,然后求一下现今的最短路,维护新最短路的前驱,并且判断多条最短路时,前驱优先选择非1号点的即可,事实上,由于我们在跑最短路时,1号点只会在开始时更新1次,故只需要在最短路更新或相等时,修改前驱即可。
总复杂度为$O((m+k) \log n) / O(n+m+k) $
T1 小Z切课本(cut)
Description
小Z厌恶数学,他决定将数学课本切成一块一块的。他的课本是一个n*m的矩形,小Z决定切K刀,每刀他可以横着切或者竖着切,但是切成的矩形的长和宽都必须是整数。当然,小Z不会做出两次相同的操作。
不巧的是,小Z的数学老师知道了他这个行为,并且刁钻的老师肯定会找到切出的矩形中面积最小的那一块来D他,所以小Z想知道最优情况下面积最小的那一块面积最大能是多少?
Input
输入数据只包含一行三个整数n,m,k,含义如题目所述。
Output
输出一个数字,表示答案。如果没有合法的方案,输出-1。
Sample Input
6 4 2
Sample Output
8
Hint
Subtask1 (20 points) 满足 \(n,m \leq 10\)
Subtask2 (20 points) 满足\(n,m \leq 5000\)
Subtask3 (20 points) 满足\(n,m \leq 10^7\)
Subtask4 (40 points) 满足\(n,m \leq 10^9\)
Solution
可以简单的证明出,如果切割次数允许只在同一个方向切,肯定是最优的,
否则,肯定是将长边切满之后再切短边最优,因此只需要使得切的边最小的尽可能大,所以要尽量等分,最后计算一下答案就好了。
时空复杂度均为\(O(1)\)
Code
#include <stdio.h> #define R register #define ll long long #define AK_titoly ditoly #define max(a,b) ((a)>(b)?(a):(b)) #define file(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout); inline int read(){ R int x; R bool f; R char c; for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-'); for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0'); return f?-x:x; } int n,m,k; int main(){ file(cut); n=read(),m=read(),k=read(); if (k-n-m+2>0) return 0*puts("-1"); if (n>m) n^=m,m^=n,n^=m; if (k>=m) printf("%d\n",n/(k-m+2)); else printf("%lld\n",max(1ll*n*(m/(k+1)),1ll*m*(n/(k+1)))); return 0; }
T2 小Z爱数组(array)
Description
小Z最喜欢数组了,现在他得到了由n个正整数组成的数组ai,他想构造一个相同大小的正整数数组bi满足两个数组的差异度\(\Sigma |ai -bi|\)最小。特殊的是,bi数组的所有元素必须满足两两互质。
Input
第一行一个数n,表示数组大小。
接下来一行n个正整数ai,表示给定的数组。
Output
输出一行n个正整数bi,表示答案。
输出的数字必须满足\(1 \leq bi \leq 10^9\)。如果有多个答案,你可以输出任意一个。
Sample Input
5
1 6 4 2 8
Sample Output
1 5 4 1 9
Hint
Subtask1 (20points) 满足$ n \leq 8 , 1 \leq ai \leq 5$
Subtask2 (30points) 满足$ n \leq 50 , 1 \leq ai \leq 15$
Subtask3 (50points) 满足$ n \leq 100 , 1 \leq ai \leq 30$
Solution
容易发现\(1 \leq bi \leq 58\),如果\(bi>58\) 可以证明用1替代是等价或更优的,显然,58以内的所有质数只能在整个序列中作为最多一个数的质因子出现,经计算的,58以内的质数个数为16个,故所有质数的状态只有\(2^{16}\)种情况,考虑状态压缩,预处理出1~58中每个数所拥有的质因子集合,使用状态压缩DP即可通过。状态转移方程为:\[f[i][S|set[j]]=f[i-1][S]+|ai-j|(1 \leq j \leq 58 \vee set[j]\cap S = \phi )\]
其中\(set[j]\)表示j含有的质因数集合,\(f[i][S]\)表示前i个位置,质因数状态为S的最优答案。
总复杂度为\(O(58n*2^{16})/O(n*2^{16})\)。
Code
#include <stdio.h> #include <string.h> #define R register #define MN 105 #define inf 0x3f3f3f3f #define AK_titoly ditoly #define file(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout); inline int read(){ R int x; R bool f; R char c; for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-'); for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0'); return f?-x:x; } inline int abs(int x){return x<0?-x:x;} int a[MN],f[MN][1<<16],pre[MN][1<<16],set[MN],n,pn,ans=0,b[MN]; bool ud[MN]; void init(){ for (R int i=2; i<59; ++i) if (!ud[i]){ for (R int j=1; j<=58/i; ++j){ ud[i*j]=1; set[i*j]|=(1<<pn); }++pn; } } int main(){ file(array);init();n=read(); for (R int i=1; i<=n; ++i) a[i]=read(); memset(f,0x3f,sizeof(f)); for (R int S=0; S<(1<<16); ++S) f[0][S]=0; for (R int i=1; i<=n; ++i) for (R int j=1; j<59; ++j) for (R int S=0; S<(1<<16); ++S) if (!(set[j]&S)&&f[i][S|set[j]]>f[i-1][S]+abs(j-a[i])) f[i][S|set[j]]=f[i-1][S]+abs(j-a[i]),pre[i][S|set[j]]=j; for (R int S=1; S<(1<<16); ++S) if (f [ans]>f [S]) ans=S; for (R int i=n; i; --i) b[i]=pre[i][ans],ans^=set[pre[i][ans]]; for (R int i=1; i<=n; ++i) printf("%d ",b[i]); return 0; }
T3 小Z爱修路(road)
Description
L国包含n个城市和m条双向道路,第i条道路连接ui,vi两个城市,距离为ti,这些道路将所有n个城市连接在一起。明年,L国将会在首都,也就是1号城市举办一年一度的noi,所以L国的国王委托小Z新建一些道路来减少一些城市到达首都的距离。小Z很快修好了道路,但是他却不是很满意。他想知道最多可以少新建多少道路,满足首都到所有城市的最短路长度和现在相同。
Input
第一行读入三个数字n,m,k,依次表示城市的数量,原有道路的数量和新建道路的数量。
接下来m行,每行三个数字ui,vi,ti,表示一条原有的道路
最后k行,每行两个数字si,wi,表示一条新建的道路连接1和si,距离为wi。
Output
输出一个整数,表示最多能少修建多少条新建的道路。
Sample Input
3 2 2
1 2 1
2 3 1
2 2
3 1
Sample Output
1
Hint
对于20%的数据,满足\(n,m,k \leq 100\);
另有20%的数据,满足\(k \leq 4\)
对于100%的数据,满足\(n,k \leq 50000 , m \leq 200000 , 1 \leq ti,wi \leq 10^9 si \geq 2\)
Solution
考虑一条新建的边一定会被修建的原因,显然是因为2个原因:
1.从1号点到这条边的另一端的最短路被修改了
2.最短路一定包含新的修建的边
考虑如何维护上述两种情况,显然,只需要求一次原先的最短路,然后求一下现今的最短路,维护新最短路的前驱,并且判断多条最短路时,前驱优先选择非1号点的即可,事实上,由于我们在跑最短路时,1号点只会在开始时更新1次,故只需要在最短路更新或相等时,修改前驱即可。
总复杂度为$O((m+k) \log n) / O(n+m+k) $
Code
#include <stdio.h> #include <string.h> #define MN 50005 #define MM 200005 #define M (1<<16) #define R register #define ll long long #define inf 0x3f3f3f3f #define INF 0x3f3f3f3f3f3f3f3fll #define AK_titoly ditoly #define file(f) freopen(#f".in","r",stdin);freopen(#f".out","w",stdout); inline int read(){ R int x; R bool f; R char c; for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-'); for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0'); return f?-x:x; } inline int min(R int a,R int b){return a<b?a:b;} struct node{ll v;int pos;}T[M<<1]; int to[MM+MN<<1],nxt[MM+MN<<1],v[MM+MN<<1],h[MN],pre[MN],n,m,k,en,ans; ll dis[MN],dis2[MN]; inline void ins(int x,int y,int vl){to[++en]=y,nxt[en]=h[x],v[en]=vl,h[x]=en;} inline node min(node a,node b){return a.v<b.v?a:b;} inline void A(int k,ll v){for (T[k+=M].v=v; k>>=1; T[k]=min(T[k<<1],T[k<<1|1]));} inline void dij(int u,ll *dis){ memset(pre,0,sizeof(pre)); memset(T,0x3f,sizeof(T));for (R int i=1; i<=n; ++i) T[i+M].pos=i; A(u,0);dis[u]=0;for (R int i=1; i<=n; ++i){ u=T[1].pos;A(u,INF);for (R int j=h[u]; j; j=nxt[j]){ if (dis[to[j]]>=dis[u]+v[j]) pre[to[j]]=u; if (dis[to[j]]>dis[u]+v[j]) A(to[j],dis[to[j]]=dis[u]+v[j]); } } } int main(){ file(road); memset(dis,0x3f,sizeof(dis)); memset(dis2,0x3f,sizeof(dis)); n=read(),m=read(),k=read(); for (R int i=1; i<=m; ++i){ R int x=read(),y=read(),v=read(); ins(x,y,v);ins(y,x,v); }dij(1,dis);for (R int i=1; i<=k; ++i){ R int x=1,y=read(),v=read(); ins(x,y,v);ins(y,x,v); }dij(1,dis2);for (R int i=2; i<=n; ++i) if (dis2[i]<dis[i]&&pre[i]==1) ++ans; printf("%d\n",k-ans); return 0; }
相关文章推荐
- NOIP校内模拟赛1
- 2017.8.15 校内模拟赛
- 【20170521校内模拟赛】热爱生活的小Z
- 2017.9.2 校内模拟赛
- 2017.9.17校内noip模拟赛解题报告
- 【20171029校内模拟赛】无题
- 20171108校内模拟赛
- 【20170604校内模拟赛】香蕉
- 【20170906校内模拟赛】
- 【20170923校内模拟赛】
- 2018.10.17校内模拟赛:T2神光
- 2016.10.18出题人丁明朔校内模拟赛反思
- 5.13 校内模拟赛
- 20171107校内模拟赛
- 2010年9月22号校内ACM省赛前模拟赛教师总结外加部分结题报告
- 【20170528校内模拟赛】
- 【20170915校内模拟赛】
- 【20170902校内模拟赛】
- 【20170920校内模拟赛】小Z爱学习
- 校内人气之星