Tim的模拟赛(提高组)
试题名称 | 时间限制 | 内存限制 | 测试点数目 | 每个测试点分值 |
买花 flower | 1s | 512M | 10 | 10 |
购物 Shopping | 1s | 512M | 10 | 10 |
配饰ornament | 1s | 512M | 10 | 10 |
幸福的道路Race | 1s | 512M | 10 | 10 |
买花Flower
【问题描述】
又到了一年一度的七夕节,逢此佳节,小T当然是要浪漫一下,去给小L买花。(虽然……TAT),今年,小T由于经费充足,因此他制定了一个特别的买花计划:买M束花,使得任意两束花的支数都不同,并且,尽管经费充足,也不能乱挥霍,因此小T决定对于这M束花,编号为1到M,第i束花恰好有i支花。
然而,计划总是赶不上变化。直到七夕前一天,小T才得知,小L最讨厌和M互质的数字,因此,小L会扔掉所有支数与M互质的花束。小T非常伤心,但是由于智商有限,小T只会按照原定计划进行。现在,小T的经费一共支持按照计划最多买N束花,但是,小T也可以选择买少于N束花。假如小T买了M束花,那么,第i束花仍然恰好有i支。
现在,小T希望聪明的你帮他制定一个最好的方案,使得被小L扔掉花束的比例尽可能小。
PS:看不懂题面的可以看这个:
即求一个小于等于M的数N,使得phi(N)/N最小,其中phi(N)是与N互质的数的个数。
例如phi(4)=2,因为1,3和4互质。
【输入格式】
一行一个正整数M。
【输出格式】
一行一个正整数N。
【样例输入】
10
【样例输出】
6
数据范围:
对于30%的数据,N<=1000
对于60%的数据,N<=1000,000,000
对于100%的数据,N<=10^40
#include <cstdio> #include <cstring> int notprime[5000000]; int prime[5000000]; char s[50]; int n[50]; int a[50]; int ans[50]; int tot; bool compare(int a[],int n[]){ if (n[0]>a[0]) return true; else if (n[0]<a[0]) return false; else{ for (int i=a[0];i>0;i--){ if (a[i]<n[i]) return true; else if (a[i]>n[i]) return false; } } return false; } void mul(int a[],int x){ int c[50]; int len=a[0]+7; int g=0; memset(c,0,sizeof(c)); for (int i=1;i<=len;i++){ c[i]=a[i]*x+g; g=c[i] / 10; c[i] %= 10; } while (c[len]==0) len--; c[0]=len; memcpy(a,c,sizeof(c)); } int main(){ freopen("flower.in","r",stdin); freopen("flower.out","w",stdout); scanf("%s",s); n[0]=strlen(s); for (unsigned int i=0;i<n[0];i++) n[n[0]-i]=s[i]-'0'; notprime[1]=true; for (int i=2;i<=100000;i++){ if (!notprime[i]){ for (int j=i+i;j<=2000000;j+=i) notprime[j]=true; } } for (int i=1;i<=2000000;i++){ if (!notprime[i]) prime[++tot]=i; } a[0]=a[1]=1; for (int i=1;i<=tot;i++){ if (compare(a,n)){ memcpy(ans,a,sizeof(ans)); mul(a,prime[i]); }else break; } for (int i=ans[0];i>0;i--){ printf("%d",ans[i]); } putchar('\n'); return 0; }
购物shopping
【问题描述】
小T和小L都很喜欢购物,但是,众所周知,小T和小L都很懒,因此,在这么热的天,他们宁可在淘宝上买东西。现在,货架上有N件物品,由于小T和小L共用一台电脑,他们决定轮流购买自己喜欢的东西。由于小T和小L的审美完全不同,因此,每件物品对小T的价值为A_i,对小L的价值为B_i。因为小L和小T是好朋友,因此他们在满足自己利益的时候也会为别人着想。小T总是会选择对自己价值最大的物品,如果有多个,则选择其中对小L价值最小的。而小L就聪明很多(因为小L会算!= =||),他总是选择会使自己最后得到的物品总价值最多的物品,如果有多个,他会选择使得小L最后得到总价值也最多的物品。
现在,要求聪明的你帮助小L和小T计算按照他们的策略最后分别得到的物品的价值。
【输入格式】
第一行一个数N表示物品数。
第二行为“L”或者“T”,表示L或者T先选取物品。
第三到第N+2行,每行两个数A_i和B_i
【输出格式】
一行用空格隔开两个数P,Q分别表示小T和小L最后得到物品的总价值。
【样例输入】
4
L
100 80
70 80
50 80
30 50
【样例输出】
170 130
数据范围:
N<=100
配饰(ornament)
【问题描述】
但是小L想考验一下小T,所以,他给小T出了一个难题.
他拿出了他所有的配饰并摆成两列,如果两个配饰的型号一样并且出现在不同列中,那么我们就可以认为这两个配饰为情侣配饰.另外,由于某些不为人知的原因,我们规定,在顺序选取的情况下,每选定的一对配饰必须比前面选定的一对配饰的型号要大.小T最多能够选取多少对配饰呢?
【输入格式】
共四行
第一行一个数N 表示第一列配饰的个数
第二行N个数 分别表示第一列配饰的型号
第三行一个数M 表示第二列配饰的个数
第四行M个数 分别表示第二列配饰的型号
【输出格式】
仅一个数K,表示最多能选取的情侣配饰的对数.
【样例输入】
5
1 4 2 6 8
5
1 5 0 2 4
【样例输出】
2
数据范围:
30%的数据 n,m<=10
70%的数据 n,m<=100
100%的数据 n,m<=5000
#include <cstdio> int n,m; int a[5010],b[5010]; int f[5010][5010]; int ans; int main(){ freopen("ornament.in","r",stdin); freopen("ornament.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;i++){ scanf("%d",&a[i]); } scanf("%d",&m); for (int i=1;i<=m;i++){ scanf("%d",&b[i]); } for (int i=1;i<=n;i++){ int ma=0; for (int j=1;j<=m;j++){ f[i][j]=f[i-1][j]; if (a[i]==b[j]){ f[i][j]=ma+1; } if (a[i]>b[j] && ma<f[i-1][j]) ma=f[i-1][j]; if (f[i][j]>ans) ans=f[i][j]; } } printf("%d\n",ans); return 0; }
幸福的道路(race)
【问题描述】
小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光.
他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图.
他们不愿枯燥的每天从同一个地方开始他们的锻炼,所以他们准备给起点标号后顺序地从每个起点开始(第一天从起点一开始,第二天从起点二开始……). 而且他们给每条道路定上一个幸福的值.很显然他们每次出发都想走幸福值和最长的路线(即从起点到树上的某一点路径中最长的一条).
他们不愿再经历之前的大起大落,所以决定连续几天的幸福值波动不能超过M(即一段连续的区间并且区间的最大值最小值之差不超过M).他们想知道要是这样的话他们最多能连续锻炼多少天(hint:不一定从第一天一直开始连续锻炼)?
现在,他们把这个艰巨的任务交给你了!
【输入格式】
第一行包含两个整数N, M(M<=10^9).
第二至第N行,每行两个数字Fi , Di, 第i行表示第i个节点的父亲是Fi,且道路的幸福值是Di.
【输出格式】
最长的连续锻炼天数
【样例输入】
3 2
1 1
1 3
【样例输出】
3
数据范围:
50%的数据N<=1000
80%的数据N<=100000
100%的数据N<=1000000
//树形DP+队列 #include <cstdio> #include <cstring> #include <cmath> #include <iostream> #define INF 214748364 struct edge{ int x,w,next; }e[2000010]; int tot; int n,m; int fa[1000010]; int w[1000010]; int k[1000010]; int f[1000010][3]; int len[1000010]; int G[1000010][20]; int F[1000010][20]; int ans; int max(int a,int b){return a>b?a:b;} int min(int a,int b){return a<b?a:b;} void add(int x,int y,int z){ e[++tot].x=y; e[tot].w=z; e[tot].next=k[x]; k[x]=tot; } void dp1(int x){ for (int t=k[x];t;t=e[t].next){ dp1(e[t].x); if (f[x][1]<f[e[t].x][1]+e[t].w){ f[x][2]=f[x][1]; f[x][1]=f[e[t].x][1]+e[t].w; }else if (f[x][2]<f[e[t].x][1]+e[t].w){ f[x][2]=f[e[t].x][1]+e[t].w; } } } void dp2(int x){ if (fa[x]!=0){ if (f[fa[x]][1]==f[x][1]+w[x]) f[x][0]=max(f[fa[x]][0],f[fa[x]][2])+w[x]; else f[x][0]=max(f[fa[x]][0],f[fa[x]][1])+w[x]; } for (int t=k[x];t;t=e[t].next){ dp2(e[t].x); } } int main(){ freopen("race.in","r",stdin); freopen("race.out","w",stdout); scanf("%d%d",&n,&m); for (int i=2;i<=n;i++){ int x,y; scanf("%d%d",&x,&y); add(x,i,y); fa[i]=x; w[i]=y; } dp1(1); dp2(1); for (int i=1;i<=n;i++){ len[i]=max(f[i][0],f[i][1]); G[i][0]=F[i][0]=len[i]; // printf("%d\n",len[i]); } for (int j=1;j<=(int)(log10((double)n)/log10(2.0));j++){ for (int i=1;i<=(n-(1 << j)+1);i++){ G[i][j]=min(G[i][j-1],G[i+(1 << (j-1))][j-1]); F[i][j]=max(F[i][j-1],F[i+(1 << (j-1))][j-1]); } } int head=1,tail=0; int mi=100000000,ma=-10000000; for (int i=1;i<=n;i++){ tail++; if (len[tail]>ma) ma=len[i]; if (len[tail]<mi) mi=len[i]; while (ma-mi>m && head<tail){ head++; int t=(int)(log10((double)(tail-head+1))/log10(2.0)); ma=max(F[head][t],F[tail-(1 << t)+1][t]); mi=min(G[head][t],G[tail-(1 << t)+1][t]); } if (tail-head+1>ans) ans=tail-head+1; } printf("%d\n",ans); return 0; }