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;
}
浙公网安备 33010602011771号