开学第二测

                开学第二测(好像是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;
}
20分记忆化搜索
#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;
    }
}
学姐的40分快速幂暴力
#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;
    }
}
学姐的30分暴力
#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;
}
标程(内带题解)

 

posted @ 2018-03-25 16:22  落云小师妹  阅读(264)  评论(5编辑  收藏  举报