2017-10-02清北模拟赛
P98
zhx
竞赛时间: ????年??月??日??:??-??:??
题目名称
a
b
c
名称
a
b
c
输入
a.in
b.in
c.in
输出
a.out
b.out
c.out
每个测试点时限
1s
1s
1s
内存限制
256MB
256MB
256MB
测试点数目
10
10
10
每个测试点分值
10
10
10
是否有部分
无
无
无
题目类型
传统
传统
传统
注意 事项 (请务必仔细阅读) (请务必仔细阅读) :
P98 zhxa
第 2 页 共 6 页
T1 a
【问题描述】
你是能看到第一题的 friends呢。
—— hja
世界上没有什么比卖的这 贵弹丸三还令人绝望事了,所以便么一道题。定义 𝑓(𝑥)为满足 (𝑎×𝑏)|𝑥的有序正整数对 (𝑎,𝑏)的个数。现在给定 𝑁,求 Σ𝑓(𝑖)𝑁𝑖=1
【输入格式】
一行个整数 𝑁。
【输出格式】
一行个整数代表答案 。
【样例输入】
6
【样例输出】
25
【数据范围与规定】
对于 30%的数据, 1≤𝑛≤100。
对于 60%的数据, 1≤𝑛≤1000。
对于 100%的数据, 1≤𝑛≤1011.
P98 zhxb
第 3 页 共6 页
1 /* 2 60 n^2做法,找规律发现, 3 对于每一个f[i]= i的每个约数的因子总个数、 4 处理处f[i]累加ans便可 5 但是数组开大爆零了 6 */ 7 #include <cstdio> 8 9 #define LL long long 10 inline void read(LL &x) 11 { 12 x=0; register char ch=getchar(); 13 for(; ch>'9'||ch<'0'; ) ch=getchar(); 14 for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0'; 15 } 16 const int N(1e8+5); 17 LL n,ans,tmp,cnt[N],num[N]; 18 19 int Presist() 20 { 21 freopen("a.in","r",stdin); 22 freopen("a.out","w",stdout); 23 read(n); 24 for(int i=1; i<=n; ++i) 25 { 26 for(int j=1; j<=i; ++j) 27 if(i%j==0) cnt[i]++,num[++tmp]=j; 28 for(int j=1; j<=tmp; ++j) 29 ans+=cnt[num[j]]; tmp=0; 30 } 31 printf("%lld\n",ans); 32 return 0; 33 } 34 35 int Aptal=Presist(); 36 int main(int argc,char*argv[]){;}
1 /* 2 将条件 满足(a,b)\x 的a,b数对个数 看作为 3 存在 a*b*c<=n 的c 的取值 4 则原问题转化为 找出a*b*c<=n 的a,b,c的组成发难书 5 可以考虑 假设 a<=b<=c,通过枚举a,b累加ans 6 可以发现a*a*a<=n,b*b<=n/a,所以复杂度 根号5/6 7 */ 8 #include <cstdio> 9 10 #define LL long long 11 #ifdef WIN32 12 #define L_ "%I64d" 13 #else 14 #define L_ "%lld" 15 #endif 16 17 inline void read(LL &x) 18 { 19 x=0; register char ch=getchar(); 20 for(; ch>'9'||ch<'0'; ) ch=getchar(); 21 for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0'; 22 } 23 LL n,ans,cnt; 24 25 int Presist() 26 { 27 read(n); 28 for(LL i=1,t; i*i<=(t=n/i); ++i) 29 for(LL j=i+1; j*j<=t; ++j) 30 cnt+=n/(i*j)-j; //此时假定a<b<c,cnt累加三个数的不同种类数 31 ans+=cnt*6; cnt=0; // C(3,3) 累加ans 32 for(LL i=1,t; (t=i*i)<=n; ++i) 33 { 34 cnt+=n/t; //此时假定a=b ,cnt累加a的种类数 35 if(t<=n/i) ans++,cnt--;//此时a==b==c单独累加ans 36 } 37 ans+=cnt*3; //三个数中仅存在两个数相同的组合数 38 printf(L_ "\n",ans); 39 return 0; 40 } 41 42 int Aptal=Presist(); 43 int main(int argc,char*argv[]){;}
T2 b
【问题描述】
你是能看到第二题的 friends呢。
—— laekov
Hja和 Yjq为了 抢男主 角打了 起来 ,现在 他们 正在 一棵树 上决斗 。Hja在 A点,Yjq在 B点,Hja先发制人 开始 移动 。每次 他们 可以 沿着 一条边 移动 ,但 一旦 一条边 被对方 走过了 自己 就不能 再走这条边 了。每条 边上 都有 权值 ,他们 都希望 自己 的权值 尽量多 。现在 给你 这棵树 以及 他们 俩开始 的位置 ,问 Hja能 够获得 的最大权值 。
【输入格式】
第一行 两个 整数 𝑁,𝑀,代表 树的点数 和询问 的个数 。
接下来 𝑁−1行每行 三个 整数 𝑎,𝑏,𝑐,代表 从𝑎到𝑏有一条 权值 为𝑐的边 。
接下来 𝑀行,每行 两个整数 𝐴,𝐵代表 一次 询问 。
【输出格式】
对于 每次 询问 ,输出 一个 整数 代表 答案 。
【样例输入1】
2 1
1 2 3
1 2
【样例输出1】 3
【样例输入2】
3 2
1 2 3
1
3 2 3
1 3
【样例输出2】 3 4
P98 zhxb
第 4 页 共 6 页
【数据范围与规定】
对于 30%的数据 ,1≤𝑁,𝑀≤1000。
对于另外 30%的数据 ,𝑀=1。
对于 100%的数据, 1≤𝑁,𝑀≤105,0≤𝑐≤103,1≤𝑎,𝑏,𝐴,𝐵≤𝑁。
1 /* 2 分情况讨论增加ans 3 倍增LCA 维护一条链上的点权和 4 */ 5 #include<algorithm> 6 #include<cstdlib> 7 #include<cstring> 8 #include<cstdio> 9 10 using namespace std; 11 12 const int maxn=100010; 13 14 int n,m,en; 15 int z[maxn*3],f[maxn][20],q[maxn],depth[maxn]; 16 sum[maxn*3][2],fd[maxn],start[maxn],end[maxn],value[maxn]; 17 18 struct edge 19 { 20 int e,d; 21 edge *next; 22 }*v[maxn],ed[maxn<<1]; 23 24 void add_edge(int s,int e,int d) 25 { 26 en++; 27 v[s].e=e;v[s].d=d; 28 ed[en].next=v[s];v[s]=ed+en; 29 } 30 31 int get(int p,int d) 32 { 33 if (d==-1) return p; 34 int x=0; 35 while (d) 36 { 37 if (d&1) p=f[p][x]; 38 d>>=1; 39 x++; 40 } 41 return p; 42 } 43 44 int get_lca(int p1,int p2) 45 { 46 if (depth[p1]<depth[p2]) swap(p1,p2); 47 p1=get(p1,depth[p1]-depth[p2]); 48 int x=0; 49 while (p1!=p2) 50 { 51 if (!x || f[p1][x]!=f[p2][x]) 52 { 53 p1=f[p1][x]; 54 p2=f[p2][x]; 55 x++; 56 } 57 else x--; 58 } 59 return p1; 60 } 61 62 int calc(int p1,int p2) 63 { 64 if (p1==f[p2][0]) return value[1]-value[p2]; 65 else return value[p1]+fd[p1]; 66 } 67 68 int calcp(int p,int v) 69 { 70 int l=start[p]-1,r=end[p]; 71 while (l+1!=r) 72 { 73 int m=(l+r)>>1; 74 if (v>z[m]) l=m; 75 else r=m; 76 } 77 return r; 78 } 79 80 int main() 81 { 82 freopen("b.in","r",stdin); 83 freopen("b.out","w",stdout); 84 85 scanf("%d%d",&n,&m); 86 int tot=0; 87 for (int a=1;a<n;a++) 88 { 89 int s,e,d; 90 scanf("%d%d%d",&s,&e,&d); 91 tot+=d; 92 add_edge(s,e,d); 93 add_edge(e,s,d); 94 } 95 depth[1]=1; 96 int front=1,tail=1; 97 q[1]=1; 98 for (;front<=tail;) 99 { 100 int now=q[front++]; 101 for (edge *e=v[now];e;e=e->next) 102 if (!depth[e.e]) 103 { 104 depth[e.e]=depth[now]+1; 105 fd[e.e]=e->d; 106 f[e.e][0]=now; 107 int p=now,x=0; 108 while (f[p][x]) 109 { 110 f[e.e][x+1]=f[p][x]; 111 p=f[p][x]; 112 x++; 113 } 114 q[++tail]=e.e; 115 } 116 } 117 int cnt=0; 118 for (int a=n;a>=1;a--) 119 { 120 int now=q[a]; 121 start[now]=cnt+1; 122 for (edge *e=v[now];e;e=e.next) 123 if (depth[e.e]==depth[now]+1) 124 { 125 z[++cnt]=value[e.e]+e.d; 126 value[now]+=value[e.e]+e.d; 127 } 128 z[++cnt]=tot-value[now]; 129 end[now]=cnt; 130 sort(z+start[now],z+end[now]+1); 131 sum[end[now]][0]=z[end[now]]; 132 sum[end[now]][1]=0; 133 for (int a=end[now]-1;a>=start[now];a--) 134 { 135 sum[a][0]=sum[a+1][0]; 136 sum[a][1]=sum[a+1][1]; 137 if ((a&1)==(end[now]&1)) sum[a][0]+=z[a]; 138 else sum[a][1]+=z[a]; 139 } 140 cnt++; 141 } 142 for (int a=1;a<=m;a++) 143 { 144 int p1,p2; 145 scanf("%d%d",&p1,&p2); 146 int lca=get_lca(p1,p2); 147 int dist=depth[p1]+depth[p2]-2*depth[lca]; 148 int delta=dist/2+(dist&1); 149 int px,px1,px2; 150 if (depth[p1]-depth[lca]<delta) px=get(p2,dist-delta); 151 else px=get(p1,delta); 152 if (depth[p1]-depth[lca]<delta-1) px1=get(p2,dist-delta+1); 153 else px1=get(p1,delta-1); 154 if (depth[p2]-depth[lca]<dist-delta-1) px2=get(p1,delta+1); 155 else px2=get(p2,dist-delta-1); 156 int ans=0; 157 if (p1==px) 158 { 159 if (p2==px) ans=sum[start[px]][0]; 160 else 161 { 162 int v2=calc(px2,px); 163 int p=calcp(px,v2); 164 ans=sum[p+1][0]+sum[start[px]][1]-sum[p][1]; 165 } 166 } 167 else 168 { 169 if (p2==px) 170 { 171 int v1=calc(px1,px); 172 int p=calcp(px,v1); 173 ans=v1+sum[p+1][1]+sum[start[px]][0]-sum[p][0]; 174 } 175 else 176 { 177 int v1=calc(px1,px); 178 int pp1=calcp(px,v1); 179 int v2=calc(px2,px); 180 int pp2=calcp(px,v2); 181 if (pp2==pp1) pp2++; 182 if (pp1>pp2) swap(pp1,pp2); 183 ans=v1+sum[pp2+1][dist&1]+sum[pp1+1][1-(dist&1)]- 184 sum[pp2][1-(dist&1)]+sum[start[px]][dist&1]-sum[pp1][dist&1]; 185 } 186 } 187 printf("%d\n",ans); 188 } 189 return 0; 190 }
P98 zhxc
第 5 页 共 6 页
T3 c
【问题描述】
你是能看到第三题的 friends呢。
—— aoao
Yjq买了 36个卡包,并且把他们排列成 6×6的阵型准备开包 。左上角是(0,0),右下角为 ,右下角为 (5,5)。为了能够开到更多的金色普通卡, 。为了能够开到更多的金色普通卡, Yjq会为每个包添加 1−5个玄学值,每可以是 个玄学值,每可以是 1−30中的一个整数。但是不同玄学值会造 中的一个整数。但是不同玄学值会造 成不同的欧气加,具体如下:
1、同一个卡包如果有两相的玄学值会无限大欧气加成。
2、同一个卡包如果 有 两个相邻的玄学值会𝐴点欧气加成。
3、相邻的两个卡包如果有 同玄学值会𝐵点欧气加成。
4、相邻的两个卡包如果有 玄学值会𝐶点欧气加成。
5、距离为 2的卡包如果有 相同玄学值会𝐷点欧气加成。
6、距离为 2的卡包如果有 相邻玄学值会𝐸点欧气加成。
以上的所有 加成是每存在一个符合条件就会次,如包卡以上的所有 加成是每存在一个符合条件就会次,如包卡1,2,3的玄 学值就会加两次。
但是 ,玄学值个不可控的东西即使但是 ,玄学值个不可控的东西即使但是 ,玄学值个不可控的东西即使但是 ,玄学值个不可控的东西即使但是 ,玄学值个不可控的东西即使但是 ,玄学值个不可控的东西即使但是 ,玄学值个不可控的东西即使但是 ,玄学值个不可控的东西即使但是 ,玄学值个不可控的东西即使但是 ,玄学值个不可控的东西即使但是 ,玄学值个不可控的东西即使但是 ,玄学值个不可控的东西即使但是 ,玄学值个不可控的东西即使但是 ,玄学值个不可控的东西即使但是 ,玄学值个不可控的东西即使但是 ,玄学值个不可控的东西即使但是 ,玄学值个不可控的东西即使但是 ,玄学值个不可控的东西即使Yjq也只能自己决定 也只能自己决定 也只能自己决定 也只能自己决定 也只能自己决定 也只能自己决定 也只能自己决定 (2,2),(2,3),(3,2),(3,3)这几包卡的玄学值。为了能够抽到更多金色普通, 这几包卡的玄学值。为了能够抽到更多金色普通, Yjq想知道自己能够获得的最 少的欧气加成是多。 注意 你只能 修改 玄学值 ,不能 修 改玄学值 的个数 。
【输入格式】
输入的第一行有 5个整数 𝐴,𝐵,𝐶,𝐷,𝐸。
接下去有 6×6的代表初始玄学值。
每个玄学值为 [𝑛:𝑎1,𝑎2,⋯,𝑎𝑛]的描述形式。
【输出格式】
一行个整数代表答案。
【样例输入】
5 4 3 2 1
[1:1][2][3][4][5][6]
[1:1][2][3][4][5][6]
[1:1][2][5:1,2,3,4,5][5][6]
[1:1][ 1:2][5:1,2,3,4,5][5][6]
[1:1][2][3][4][5][6]
[1:1][2][3][4][5][6]
P98 zhxc
第 6 页 共 6 页
【样例输出】
250
【数据规模与约定】
对于 100%的数据, 1≤𝐴,𝐵,𝐶,𝐷,𝐸≤100,1≤𝑛≤5,1≤𝑎𝑖≤30。有部分 。有部分 。
1 /* 2 九维DP 3 维护点之间的最小价值 4 */ 5 #include<algorithm> 6 #include<cstdlib> 7 #include<cstring> 8 #include<cstdio> 9 10 using namespace std; 11 12 #define now pre[a][b][c][d][e][s1][s2][s3][s4] 13 #define dis(a,b,c,d) (abs(a-c)+abs(b-d)) 14 15 const int INF=0x3f3f3f3f; 16 17 int A,B,C,D,E,num[10][10],value[10][10][10],delta[10][10][40],dp[31][6][6][6][6][2][2][2][2]; 18 19 char s[500]; 20 21 bool map[6][6][6][6]; 22 23 int main() 24 { 25 freopen("c.in","r",stdin); 26 freopen("c.out","w",stdout); 27 28 scanf("%d%d%d%d%d",&A,&B,&C,&D,&E); 29 for (int a=0;a<6;a++) 30 { 31 scanf("%s",s); 32 int p=0; 33 for (int b=0;b<6;b++) 34 { 35 int px=p; 36 while (s[px]!=']') 37 px++; 38 p++; 39 num[a][b]=s[p]-'0'; 40 p++; 41 p++; 42 for (int c=1;c<=num[a][b];c++) 43 { 44 int v=0; 45 while (s[p]>='0' && s[p]<='9') 46 { 47 v=v*10+s[p]-'0'; 48 p++; 49 } 50 value[a][b][c]=v; 51 p++; 52 } 53 p=px+1; 54 } 55 } 56 int base=0; 57 for (int a=0;a<6;a++) 58 for (int b=0;b<6;b++) 59 if (a>=2 && a<=3 && b>=2 && b<=3) ; 60 else 61 { 62 sort(value[a][b]+1,value[a][b]+num[a][b]+1); 63 for (int c=2;c<=num[a][b];c++) 64 if (value[a][b][c]-value[a][b][c-1]==1) base+=A; 65 for (int c=2;c<=3;c++) 66 for (int d=2;d<=3;d++) 67 { 68 if (dis(a,b,c,d)==1) 69 { 70 for (int e=1;e<=num[a][b];e++) 71 { 72 delta[c][d][value[a][b][e]]+=B; 73 delta[c][d][value[a][b][e]-1]+=C; 74 delta[c][d][value[a][b][e]+1]+=C; 75 } 76 } 77 if (dis(a,b,c,d)==2) 78 { 79 for (int e=1;e<=num[a][b];e++) 80 { 81 delta[c][d][value[a][b][e]]+=D; 82 delta[c][d][value[a][b][e]-1]+=E; 83 delta[c][d][value[a][b][e]+1]+=E; 84 } 85 } 86 } 87 for (int c=0;c<6;c++) 88 for (int d=0;d<6;d++) 89 if (dis(a,b,c,d)<=2 && (c!=a || d!=b) && !map[a][b][c][d]) 90 { 91 map[a][b][c][d]=map[c][d][a][b]=true; 92 if (c>=2 && c<=3 && d>=2 && d<=3) ; 93 else 94 { 95 int dist=dis(a,b,c,d); 96 for (int e=1;e<=num[a][b];e++) 97 for (int f=1;f<=num[c][d];f++) 98 { 99 if (abs(value[a][b][e]-value[c][d][f])==0) 100 { 101 if (dist==1) base+=B; 102 else base+=D; 103 } 104 if (abs(value[a][b][e]-value[c][d][f])==1) 105 { 106 if (dist==1) base+=C; 107 else base+=E; 108 } 109 } 110 } 111 } 112 } 113 memset(dp,0x3f,sizeof(dp)); 114 dp[0][0][0][0][0][0][0][0][0]=base; 115 for (int a=0;a<30;a++) 116 for (int b=0;b<=num[2][2];b++) 117 for (int c=0;c<=num[2][3];c++) 118 for (int d=0;d<=num[3][2];d++) 119 for (int e=0;e<=num[3][3];e++) 120 for (int s1=0;s1<=1;s1++) 121 for (int s2=0;s2<=1;s2++) 122 for (int s3=0;s3<=1;s3++) 123 for (int s4=0;s4<=1;s4++) 124 if (dp[a][b][c][d][e][s1][s2][s3][s4]!=INF) 125 { 126 int v=dp[a][b][c][d][e][s1][s2][s3][s4]; 127 for (int sx1=0;sx1<=(b!=num[2][2]);sx1++) 128 for (int sx2=0;sx2<=(c!=num[2][3]);sx2++) 129 for (int sx3=0;sx3<=(d!=num[3][2]);sx3++) 130 for (int sx4=0;sx4<=(e!=num[3][3]);sx4++) 131 { 132 int wmt=0; 133 if (sx1) 134 { 135 wmt+=delta[2][2][a+1]; 136 if (s1) wmt+=A; 137 if (s2) wmt+=C; 138 if (s3) wmt+=C; 139 if (s4) wmt+=E; 140 } 141 if (sx2) 142 { 143 wmt+=delta[2][3][a+1]; 144 if (s1) wmt+=C; 145 if (s2) wmt+=A; 146 if (s3) wmt+=E; 147 if (s4) wmt+=C; 148 } 149 if (sx3) 150 { 151 wmt+=delta[3][2][a+1]; 152 if (s1) wmt+=C; 153 if (s2) wmt+=E; 154 if (s3) wmt+=A; 155 if (s4) wmt+=C; 156 } 157 if (sx4) 158 { 159 wmt+=delta[3][3][a+1]; 160 if (s1) wmt+=E; 161 if (s2) wmt+=C; 162 if (s3) wmt+=C; 163 if (s4) wmt+=A; 164 } 165 if (sx1 && sx2) wmt+=B; 166 if (sx1 && sx3) wmt+=B; 167 if (sx1 && sx4) wmt+=D; 168 if (sx2 && sx3) wmt+=D; 169 if (sx2 && sx4) wmt+=B; 170 if (sx3 && sx4) wmt+=B; 171 int &t=dp[a+1][b+sx1][c+sx2][d+sx3][e+sx4][sx1][sx2][sx3][sx4]; 172 if (t>v+wmt) t=v+wmt; 173 } 174 } 175 int ans=INF; 176 for (int a=0;a<=1;a++) 177 for (int b=0;b<=1;b++) 178 for (int c=0;c<=1;c++) 179 for (int d=0;d<=1;d++) 180 ans=min(ans,dp[30][num[2][2]][num[2][3]][num[3][2]][num[3][3]][a][b][c][d]); 181 printf("%d\n",ans); 182 183 return 0; 184 }