开学第二测
开学第二测(好像是qbxt zhx出的题)
P69
题目名称 |
希望 | 残 | 党 |
名称 | kami | na | wosa |
输入 | kami.in | na.in | wosa.in |
输出 | kami.out | na.out | wosa.out |
每个测试点时限 | 1 秒 | 1 秒 | 1 秒 |
内存限制 | 512MB | 512MB | 512MB |
测试点数目 | 10 | 10 | 10 |
每个测试点分值 | 10 | 10 | 10 |
是否有部分分 | 无 | 无 | 无 |
题目类型 | 传统 | 传统 | 传统 |
注意 事项(请务必仔细阅读):
T1
希望
【题目描述】
网页浏览器者有后退与前进按钮,一种实现这两个功能的方式是用两个栈,“前进栈”、“后退栈”。
这里你需要实现以下几个功能:
BACK: 如果“后退栈”为空则忽略此命令。 否则将当前两面压入“前进栈”,从“后退栈”中取出栈顶页面,并设置为当前页面。
FORWARD: 如果“前进栈”为空则忽略此命令。否则将当前两面压入“后退栈”,从“前进栈”中取出栈顶页面,并设置为当前页面。
VISIT: 将当前页面压入“后退栈”、 并将当前页面置为指定页面, 并将“前进栈”置空。
QUIT: 退出。
假设此浏览器初始页面为 http://www.acm.org/
【输入格式】
输入为一系列命令:BACK, FORWARD, VISIT 和 QUIT,页面网址为不含空格的字符串
假设任一时刻任意时刻两个栈中的元素都不会超过 100。
最后一个命令为 QUIT。
【输出格式】
输对于除 QUIT 外所有命令,输出当前页面(网址)
如果该命令被忽略则输出“Ignored”。
【样例输入】
VISIT http://acm.ashland.edu/
VISIT http://acm.baylor.edu/acmicpc/
BACK
BACK
BACK
FORWARD
VISIT http://www.ibm.com/
BACK
BACK
FORWARD
FORWARD
FORWARD
QUIT
【样例输出】
http://acm.ashland.edu/
http://acm.baylor.edu/acmicpc/
http://acm.ashland.edu/
http://www.acm.org/
Ignored
http://acm.ashland.edu/
http://www.ibm.com/
http://acm.ashland.edu/
http://www.acm.org/
http://acm.ashland.edu/
http://www.ibm.com/
Ignored
【数据范围与规定】
对于100%的数据,操作数量不超过1000,每行字符串长度不超过500。
思路:模拟
#include<map> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 1010 using namespace std; char s[101],ss[1001]; int top1,top2,num,now; int stack1[MAXN],stack2[MAXN]; map<int,string>ma; map<string,int>mm; int main(){ //freopen("lppin.txt","r",stdin); freopen("kami.in","r",stdin); freopen("kami.out","w",stdout); ma[++num]="http://www.acm.org/"; mm["http://www.acm.org/"]=num; now=1; while(cin>>s&&s[0]!='Q'){ if(s[0]=='V'){ cin>>ss; if(!mm[ss]){ ma[++num]=ss; mm[ss]=num; } top1++;stack1[top1]=now; now=mm[ss]; cout<<ss<<endl;top2=0; } else if(s[0]=='B'){ if(top1){ top2++;stack2[top2]=now; now=stack1[top1];top1--; cout<<ma[now]<<endl; } else cout<<"Ignored"<<endl; } else if(s[0]=='F'){ if(top2){ top1++;stack1[top1]=now; now=stack2[top2];top2--; cout<<ma[now]<<endl; } else cout<<"Ignored"<<endl; } } }
T2
残
【问题描述】
令f(n)为斐波那契数列第n项,其中f(0) = f(1) = 1,f(n) = f(n −1) +f(n −2)。
所以要干啥呢?
求f(f(n))。
【输入格式】
第一行一个整数T代表数据组数。
接下来T行每行一个整数n。
【输出格式】
T行每行一个整数代表答案对10 9 + 7取模的值。
【样例输入】
4
0
1
2
6
【样例输出】
0
1
1
21
【数据规模与约定】
对于20%的数据,1 ≤ n ≤ 15 。
对于40%的数据,1 ≤ n ≤ 90。
对于70%的数据,1 ≤ n ≤ 105 。
对于100%的数据,1 ≤ n ≤ 10 3 ,1 ≤ n ≤ 10 100 。
思路:矩阵快速幂 吧 (由于本人不会这个,所以用了记忆化搜索)
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #define MOD 1000000007 using namespace std; int t, n; long long f[10000005]; long long dfs(int x) { if(x == 0) return f[x]; if(f[x] != 0) return f[x]; f[x] = dfs(x-1)%MOD + dfs(x-2)%MOD; } int main() { // freopen("na.in","r",stdin); // freopen("na.out","w",stdout); scanf("%d", &t); f[0] = 0; f[1] = f[2] = 1; for(int i = 1; i <= t; i++) { scanf("%d", &n); long long m = dfs(n)%MOD; long long ans = dfs(m) %MOD; printf("%lld\n", ans); } // fclose(stdin); fclose(stdout); return 0; }
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define mod 1000000007 using namespace std; typedef long long LL; int T, n; LL t[2][2], ans[2][2], r[2][2]; void mul(LL a[2][2], LL b[2][2]) { memset(r, 0, sizeof(r)); for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) for(int k = 0; k < 2; k++) r[i][j] += a[i][k]*b[k][j], r[i][j] %= mod; for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) a[i][j] = r[i][j]; } void mul1(LL a[2][2], LL b[2][2]) { memset(r, 0, sizeof(r)); for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) for(int k = 0; k < 2; k++) r[i][j] += a[i][k]*b[k][j]; for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) a[i][j] = r[i][j]; } int main() { //freopen("lppin.txt","r",stdin); //freopen("na.in","r",stdin); //freopen("na.out","w",stdout); scanf("%d", &T); while(T--) { scanf("%d", &n); memset(ans, 0, sizeof(ans)); memset(t, 0, sizeof(t)); if(n == 0) { cout << "0" << endl; continue; } t[0][0] = t[0][1] = t[1][0] = 1; ans[0][0] = ans[0][1] = 1; long long p; if(n==1 || n==2) p = 1; else { n -= 2; while(n) { if(n & 1) mul1(ans, t); mul1(t, t); n >>= 1; } } p = ans[0][0]; memset(ans, 0, sizeof(ans)); memset(t, 0, sizeof(t)); t[0][0] = t[0][1] = t[1][0] = 1; ans[0][0] = ans[0][1] = 1; if(p==1 || p==2){ cout << "1" << endl; continue; } else { p -= 2; while(p) { if(p & 1) mul(ans, t); mul(t, t); p >>= 1; } } cout << ans[0][0] << endl; } }
#include<cstdio> #include<cstdlib> #include<cstring> using namespace std; #ifdef unix #define LL "%lld" #else #define LL "%I64d" #endif const int maxn=200; const long long mo=1000000007; const long long mo2=mo*2+2; const long long mo3=mo2*3; char s[maxn]; struct matrix { long long z[3][3]; matrix() { memset(z,0,sizeof(z)); } matrix operator*(const matrix &a)const { matrix ans; for (int b=1;b<=2;b++) for (int c=1;c<=2;c++) for (int d=1;d<=2;d++) ans.z[b][c]=(ans.z[b][c]+z[b][d]*a.z[d][c]%mo)%mo; return ans; } matrix operator+(const matrix &a)const { matrix ans; for (int b=1;b<=2;b++) for (int c=1;c<=2;c++) for (int d=1;d<=2;d++) ans.z[b][c]=(ans.z[b][c]+z[b][d]*a.z[d][c]%mo2)%mo2; return ans; } }m1,m2; struct bign { int z[maxn],l; void init() { memset(z,0,sizeof(z)); scanf("%s",s+1); l=strlen(s+1); for (int a=1;a<=l;a++) z[a]=s[l-a+1]-'0'; } long long operator%(const long long &a)const { long long b=0; for (int c=l;c>=1;c--) b=(b*10+z[c])%a; return b; } }z; long long get(long long v) { if (v==0) return 0; m1.z[1][1]=0; m1.z[1][2]=1; m2.z[1][1]=0; m2.z[1][2]=m2.z[2][1]=m2.z[2][2]=1; while (v) { if (v&1) m1=m1*m2; m2=m2*m2; v>>=1; } return m1.z[1][1]; } long long get1(long long v) { if (v==0) return 0; m1.z[1][1]=0; m1.z[1][2]=1; m2.z[1][1]=0; m2.z[1][2]=m2.z[2][1]=m2.z[2][2]=1; while (v) { if (v&1) m1=m1+m2; m2=m2+m2; v>>=1; } return m1.z[1][1]; } int main() { freopen("na.in","r",stdin); freopen("na.out","w",stdout); int t; scanf("%d",&t); for (int a=1;a<=t;a++) { z.init(); long long v1=z % mo3; v1=get1(v1); printf(LL "\n",get(v1)); } return 0; }
T3
党
【问题描述】
你现在希望组建一支足球队,一支足球队一般来说由11人组成。这11人有四种不同的职业:守门员、后卫、中锋、前锋组成。你在组队的时候必须满足以下
规则:
1、 足球队恰好由11人组成。
2、 11人中恰好有一名守门员,3-5 名后卫,2-5 名中锋,1-3 名前锋。
3、 你需要从这11人中选出一名队长。
4、 你这个足球队的价值是11人的价值之和再加上队长的价值, 也就是说队长的价值会被计算两次。
5、 你这个足球队的花费是11人的花费之和, 你的花费之和不能超过给定的上限。
现在告诉你球员的总数,每个球员的职业、价值、花费,以及花费的上限,你希望在满足要求的情况下,达到以下目标:
1、 最大化队伍的价值。
2、 在最大化队伍的价值的情况下,最小化队伍的花费。
3、 在满足以上两个要求的情况下,有多少种选择球员的方案。如果有两种方案它们的区别仅仅是队长不一样, 那么这两种方案应该被认为是一种方案。
你的任务是输出这三个值:价值、花费、方案数。
【输入格式】
第一行一个正整数N,代表可选的球员个数。
接下来N行,每行描述一个球员的信息。每行开始是一个字符串,可能的字符串有 Goalkeeper、Defender、Midfielder、Forward,分别代表该球员的职业是守门员、后卫、中锋、前锋。接下来两个数V,C,分别代表该球员的价值和花费。
最后一行一个整数,代表花费的上限。
数据保证一定存在一种解。
【输出格式】
一行三个整数,分表代表最大价值、最小花费和方案数。如果方案数超过了10 9 ,则直接输出10 9 。
思路:动规(DP),好像是背包(题解说的),不过具体是什么背包我就不知道了╮(╯▽╰)╭
#include<map> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 510 using namespace std; map<string,int>ma; int vis[MAXN]; int n,H,mmp,ansval=-1,anscost=0x7f7f7f7f,ans; struct nond{ int job,val,cost; }v[MAXN]; void dfs(int now,int sum,int val,int cost,int door,int back,int mid,int front,int head){ if(sum+n-now+1<11) return ; if(cost>H) return ; if(sum==11&&door!=0&&back>=3&&back<=5&&mid>=2&&mid<=5&&front>=1&&front<=3&&head!=0){ string s; for(int i=1;i<=n;i++) s+=char(vis[i]+'0'); s+=char(head+'0'); if(val>ansval){ ansval=val;anscost=cost; ans=1;ma[s]=1; } else if(val==ansval){ if(anscost==cost){ if(!ma[s]){ if(val==716&&ans==1){ int hh=1; } ma[s]=1;ans++; } } else if(cost<anscost){ anscost=cost; ans=1; } } return ; } if(now>n) return ; if(v[now].job==1){ if(door==0) vis[now]=1,dfs(now+1,sum+1,val+v[now].val,cost+v[now].cost,1,back,mid,front,head),vis[now]=0; if(door==0&&head==0) vis[now]=1,dfs(now+1,sum+1,val+v[now].val*2,cost+v[now].cost,1,back,mid,front,now),vis[now]=0; dfs(now+1,sum,val,cost,door,back,mid,front,head); } else if(v[now].job==2){ if(back<5) vis[now]=1,dfs(now+1,sum+1,val+v[now].val,cost+v[now].cost,door,back+1,mid,front,head),vis[now]=0; if(back<5&&head==0) vis[now]=1,dfs(now+1,sum+1,val+v[now].val*2,cost+v[now].cost,door,back+1,mid,front,now),vis[now]=0; dfs(now+1,sum,val,cost,door,back,mid,front,head); } else if(v[now].job==3){ if(mid<5) vis[now]=1,dfs(now+1,sum+1,val+v[now].val,cost+v[now].cost,door,back,mid+1,front,head),vis[now]=0; if(mid<5&&head==0) vis[now]=1,dfs(now+1,sum+1,val+v[now].val*2,cost+v[now].cost,door,back,mid+1,front,now),vis[now]=0; dfs(now+1,sum,val,cost,door,back,mid,front,head); } else if(v[now].job==4){ if(front<3) vis[now]=1,dfs(now+1,sum+1,val+v[now].val,cost+v[now].cost,door,back,mid,front+1,head),vis[now]=0; if(front<3&&head==0) vis[now]=1,dfs(now+1,sum+1,val+v[now].val*2,cost+v[now].cost,door,back,mid,front+1,now),vis[now]=0; dfs(now+1,sum,val,cost,door,back,mid,front,head); } } int cmp(nond a,nond b){ if(a.val==b.val) return a.cost<b.cost; return a.val>b.val; } int main(){ //freopen("lppin.txt","r",stdin); freopen("wosa1.in","r",stdin); freopen("wosa.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++){ char c[100];cin>>c; int y,z;cin>>y>>z;mmp+=z; if(c[0]=='G') v[i].job=1; else if(c[0]=='D') v[i].job=2; else if(c[0]=='M') v[i].job=3; else if(c[0]=='F') v[i].job=4; v[i].val=y;v[i].cost=z; } cin>>H; if(n<=20){ dfs(1,0,0,0,0,0,0,0,0); cout<<ansval<<" "<<anscost<<" "<<ans; } else if(H>=mmp){ sort(v+1,v+1+n,cmp); for(int a=3;a<=5;a++) for(int b=2;b<=5;b++){ int c=11-1-a-b; int door=0,back=0,mid=0,front=0,val=0,cost=0; if(c<1) continue; for(int i=1;i<=n;i++){ if(v[i].job==1){ if(door==0) door=1,val+=v[i].val,cost+=v[i].cost; } else if(v[i].job==2){ if(back<a) back++,val+=v[i].val,cost+=v[i].cost; } else if(v[i].job==3){ if(mid<b) mid++,val+=v[i].val,cost+=v[i].cost; } else if(v[i].job==4){ if(front<c) front++,val+=v[i].val,cost+=v[i].cost; } } val+=v[1].val; if(val>ansval){ ansval=val; ans=1; } if(val==ansval){ if(cost==anscost) ans++; else if(cost<anscost){ anscost=cost;ans=1; } } } if(ans>100) ans=1000000000; cout<<ansval<<" "<<anscost<<" "<<ans; } else { dfs(1,0,0,0,0,0,0,0,0); cout<<ansval<<" "<<anscost<<" "<<ans; } }
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define mod 1000000000 using namespace std; struct nond{ int job,val,cost; }v[501]; int n,H,ansval=-1,anscost,ans; int L[5],R[5]; int f[2][6][6][4][1001][3]; /*f[a][b][c][d][e][f]表示到花费了e元为至 a表示选的守门员,b表示选了几个后卫,c表示选了几个中锋, e表示选了几个前锋 f如果等于0表示价值,如果是1表示方案数,如果是2表示队长价值*/ int cmp(nond a,nond b){ if(a.val==b.val) return a.cost>b.cost; return a.val<b.val; } void up(int a,int b,int c,int d,int e,int val,int num,int mx){ if(f[a][b][c][d][e][0]<val){ f[a][b][c][d][e][0]=val; f[a][b][c][d][e][1]=num; f[a][b][c][d][e][2]=mx; } else if(f[a][b][c][d][e][0]==val&&f[a][b][c][d][e][2]<mx){ f[a][b][c][d][e][1]=num; f[a][b][c][d][e][2]=mx; } else if(f[a][b][c][d][e][0]==val&&f[a][b][c][d][e][2]==mx){ f[a][b][c][d][e][1]+=num; if(f[a][b][c][d][e][1]>mod) f[a][b][c][d][e][1]=mod; } } /*背包*/ void insert(int x){ for(int a=R[1]-(v[x].job==1);a>=0;a--) for(int b=R[2]-(v[x].job==2);b>=0;b--) for(int c=R[3]-(v[x].job==3);c>=0;c--) for(int d=R[4]-(v[x].job==4);d>=0;d--) for(int e=H-v[x].cost;e>=0;e--) if(f[a][b][c][d][e][1]){ int val=v[x].val+f[a][b][c][d][e][0]; up(a+(v[x].job==1),b+(v[x].job==2),c+(v[x].job==3),d+(v[x].job==4),e+v[x].cost,val,f[a][b][c][d][e][1],v[x].val); } } int main(){ freopen("wosa4.in","r",stdin); //freopen("wosa.out","w",stdout); //freopen("1wosaout.txt","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++){ char s[100];cin>>s; int x,y;cin>>x>>y; if(s[0]=='G') v[i].job=1; if(s[0]=='D') v[i].job=2; if(s[0]=='M') v[i].job=3; if(s[0]=='F') v[i].job=4; v[i].val=x;v[i].cost=y; } scanf("%d",&H); L[1]=1;R[1]=1;L[2]=3;R[2]=5; L[3]=2;R[3]=5;L[4]=1;R[4]=3; //分别表示4种人所选的人数的限制范围。 sort(v+1,v+1+n,cmp);//预处理排序(不明白啊啊啊啊,为什么这么排) f[0][0][0][0][0][1]=1; //没选的方案数。 f[0][0][0][0][0][2]=-1; //没选的队长价值(没有队长,所以设成-1) for(int i=1;i<=n;i++) insert(i); for(int a=L[1];a<=R[1];a++) for(int b=L[2];b<=R[2];b++) for(int c=L[3];c<=R[3];c++) for(int d=L[4];d<=R[4];d++) if(a+b+c+d==11) for(int e=0;e<=H;e++){ if(f[a][b][c][d][e][1]==0) continue; int val=f[a][b][c][d][e][0]+f[a][b][c][d][e][2]; if(val>ansval){ ansval=val;anscost=e; ans=f[a][b][c][d][e][1]; } else if(val==ansval&&e<anscost){ anscost=e; ans=f[a][b][c][d][e][1]; } else if(val==ansval&&e==anscost){ ans+=f[a][b][c][d][e][1]; if(ans>mod) ans=mod; } } cout<<ansval<<" "<<anscost<<" "<<ans; }