[The 14th Zhejiang University Programming Contest]

题目链接:

http://acm.zju.edu.cn/onlinejudge/showContestProblems.do?contestId=354


A.   zoj 3767 Elevator

题目意思:

判断n个人的重量是否超过电梯的总载重量。

解题思路:

水题

代码:

//#include<CSpreadSheet.h>

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

int main()
{
   //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);

   int t,n,m;

   scanf("%d",&t);
   while(t--)
   {
       scanf("%d%d",&n,&m);
       int res=0;

       for(int i=1;i<=n;i++)
       {
           int a;
           scanf("%d",&a);
           res+=a;
       }
       if(res>m)
        printf("Warning\n");
       else
            printf("Safe\n");
   }
   return 0;
}



B.  zoj 3668 Continuous Login

迭代加深搜索,因为总分组数很少,深度不会很大。

解题报告:http://blog.csdn.net/cc_again/article/details/25566503


C.  zoj 3769 Diablo III

将限制条件转化去掉后转化成背包问题,要注意常数优化,排个序&把第一个单独拿出来考虑。

解题报告:http://blog.csdn.net/cc_again/article/details/25984915


D.  zoj 3770 Ranking System

题目意思:

有n个人,每个人有一个ID、分数和进公司日期,要把这n个人分成6个等级。

分法:分数为0的人等级为1,达不到等级为3或者更高的人等级为2,分越高者等级越高,分数一样者先进公司者等级高,如果还一样谁的ID小者等级高。

告诉每个等级的人数,输出每个人所在的等级。

解题思路:

模拟

先把人按分数高+进公司日期早+ID号小的优先顺序排序,然后从等级高的开始往下分配,直到每个等级的人都分配完了。注意等级1的人得0分,是固定不变的。

代码:

//#include<CSpreadSheet.h>

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define Maxn 2200

struct PP
{
    int yy,mm,dd,id,s;
    int pos,le;

}pp[Maxn];
int ans[Maxn],num[10],n,zh;

bool cmp(PP a,PP b)
{
    if(a.s!=b.s)
        return a.s>b.s;
    if(a.yy>b.yy)
        return false;
    else if(a.yy<b.yy)
        return true;
    if(a.mm>b.mm)
        return false;
    else if(a.mm<b.mm)
        return true;

    if(a.dd>b.dd)
        return false;
    else if(a.dd<b.dd)
        return true;

    return a.id<b.id;

}

int main()
{
   //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);

   int t;

   scanf("%d",&t);
   while(t--)
   {
       zh=0;
       scanf("%d",&n);
       for(int i=1;i<=n;i++)
       {
           scanf("%d%d/%d/%d%d",&pp[i].id,&pp[i].yy,&pp[i].mm,&pp[i].dd,&pp[i].s);
           //printf(":%d %d %d\n",pp[i].yy,pp[i].mm,pp[i].dd);
           if(pp[i].s>0)
                zh++;
           pp[i].pos=i;
       }
       num[6]=(int)floor(zh*0.03); //计算每个等级的人数
       num[5]=(int)floor(zh*0.07);
       num[4]=(int)floor(zh*0.2);
       num[3]=(int)floor(zh*0.3);

       sort(pp+1,pp+n+1,cmp);
       /*for(int i=1;i<=n;i++)
            printf(":%d\n",pp[i].pos);*/
       int tt=1;

       for(int i=6;i>=3;i--)
       {
           for(int j=tt;j<(tt+num[i]);j++)
               ans[pp[j].pos]=i;
           tt=tt+num[i];
       }
       for(int i=tt;i<=n;i++)
       {
           if(pp[i].s)
               ans[pp[i].pos]=2;
           else
                ans[pp[i].pos]=1;
       }

       for(int i=1;i<=n;i++)
            printf("LV%d\n",ans[i]);

   }
   return 0;
}




F.  zoj  3772 Calculate the Function

线段树维护区间的矩阵乘积后的矩阵,注意矩阵乘法的顺序。

解题报告:http://blog.csdn.net/cc_again/article/details/26093941


H.  zoj 3773 Power of Fibonacci

题目意思:

求F1^k+F2^k+...+Fn^k

n<=10^18 k<=100000  Fn为斐波拉契数列的第n项

解题思路:

数论、逆元、二次剩余。终于知道带根号的数模上一个数怎么处理了。 

Tips:要求局部的x^(1/y) mod p 的话只要满足x是p的y次剩余,就可以由满足剩余的那个数代替运算

参考这位大神思路:http://blog.csdn.net/acdreamers/article/details/23039571

代码:

//#include<CSpreadSheet.h>

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000009
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define Maxn 110000
LL cc[Maxn],aa[Maxn],bb[Maxn];
LL n,k;

void init()
{
    cc[0]=1;
    for(LL i=1;i<=100000;i++) //阶乘
        cc[i]=cc[i-1]*i%M;
    aa[0]=bb[0]=1;
    for(LL i=1;i<=100000;i++) // a=(sqrt(5)+1)/2  b=(sqrt(5)-1)/2 用一个整数代替
    {
        aa[i]=aa[i-1]*691504013%M;
        bb[i]=bb[i-1]*308495997%M;
    }
}

LL quick(LL a,LL b)
{
    LL res=1;

    while(b)
    {
        if(b&1)
            res=res*a%M;
        b>>=1;
        a=a*a%M;
    }
    return res;
}

int main()
{
   //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);

   /*for(LL i=7000000;;i++)   5是1000000009的二次剩余 x^2=5%1000000009 x的一个解为383008016
   {
       if(i*i%M==5)
       {
           printf("%lld\n",i);
           break;
       }
   }*/
   init();
   int T;

   scanf("%d",&T);
   while(T--)
   {
       scanf("%lld%lld",&n,&k);
       LL ans=0;

       for(int r=0;r<=k;r++) //枚举C(k,r)
       {
           LL x=aa[k-r]*bb[r]%M; //a^(k-r)*b(r)
           LL y=cc[k]; //k!
           LL y1=cc[r],y2=cc[k-r];
           y=cc[k]*quick(y1,M-2)%M*quick(y2,M-2)%M; //C(k,r)  k!/(r!*(k-r)!)


           LL temp=x*(quick(x,n)-1)%M*quick(x-1,M-2)%M; //等比数列求和 t*(t^n-1)/(t-1)
           if(x==1) //当公比为1时不能按照这个来求 都为1 相加得n
                temp=n%M;
           temp=temp*y%M; //乘上C(k,r)
           if(r&1)
                ans=((ans-temp)%M+M)%M;
           else
                ans=(ans+temp)%M;
       }
       LL temp=quick(383008016,M-2); //最后还有个(1/sqrt(5))^k次方 先求出逆元

       ans=ans*quick(temp,k)%M; //相乘即可得出结果
       printf("%lld\n",ans);

   }
   return 0;
}
/*
383008016

*/


I.  zoj 3775 ?(>_0)!

题目意思:

给一种语言,告诉规则,让你判断这种语言输出的结果和源代码是否一样。

解题思路:

实际上只用判断’_'和‘!'的个数就可以解决问题了。

’_'最多只能有一个,因为它的意思是把源代码按原型输出一遍,如果存在‘!'那么原文一定是“hello, world!hello, world!..."且出现的次数和‘!'出现的次数应该一样。

注意考虑空串的情况。

代码:

//#include<CSpreadSheet.h>

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define Maxn 440

char save[Maxn];

char ba[]={"Hello, world!"};

int main()
{
   //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);
   int t;

   scanf("%d",&t);
   getchar();

   while(t--)
   {
       gets(save);

       int len=strlen(save),ans0=0,ans1=0;

       for(int i=0;i<len;i++)
       {
           if(save[i]=='_')
                ans0++;
           else if(save[i]=='!')
                ans1++;
       }
       if(ans0>1) //'_'超过1个肯定不行
       {
           printf("No\n");
           continue;
       }
       if(ans0==1) //恰好为1个
       {
           if(ans1) //如果存在'!'也不行
           {
               printf("No\n");
           }
           else
                printf("Yes\n");
          continue;
       }
       if(ans1==0)  //没有'_' 且没有'!'
       {
           if(!len) //如果是空串 这种情况没考虑的话会wa
                printf("Yes\n");
           else      //否则不行
                printf("No\n");
           continue;
       }

       bool flag=true;  //判断'!'的个数是否和“hello, world!"出现的个数一样
       int i=0,j=0;

       while(i<ans1&&j<len)
       {
           if(strncmp(save+j,ba,13)!=0)
           {
               flag=false;
               break;
           }
           i++;
           j+=13;
       }
       if(i!=ans1||j!=len)
            flag=false;
       if(!flag)
            printf("No\n");
       else
            printf("Yes\n");



   }
   return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值