题目链接:
http://acm.zju.edu.cn/onlinejudge/showContestProblems.do?contestId=354
题目意思:
判断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;
}
迭代加深搜索,因为总分组数很少,深度不会很大。
解题报告:http://blog.csdn.net/cc_again/article/details/25566503
将限制条件转化去掉后转化成背包问题,要注意常数优化,排个序&把第一个单独拿出来考虑。
解题报告:http://blog.csdn.net/cc_again/article/details/25984915
题目意思:
有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;
}