题目集地址 上海站2011CCPC
队内题目集地址 上海站2011CCPC
A Zombie’s Treasure Chest 思维
题目地址A Zombie’s Treasure Chest
题目大意:有两种宝石蓝宝石和红宝石,数量不限,一个宝箱容量为N,每种宝石都有一个体积和价值,放入宝箱,问宝箱中宝石的最大价值是多少。
题目思路:看起来好像是一个完全背包,但是用完全背包的解法根本行不通,因为数据量都在(
2
3
1
2^31
231)也就是1e9,暴力肯定是不行的。
我们看这个题目S1,V1,S2,V2表示蓝宝石的体积和价值红宝石的体积和价值。然后我们看他们的性价比
关于分数的比较有一个小技巧:我一开始计算分数比较大小先通分,然后将分母化为相同的值比较分子大小,其实可以这样计算
如
果
V
1
S
1
>
V
2
S
2
如果\frac{V1}{S1}>\frac{V2}{S2}
如果S1V1>S2V2则两边同时乘一个S1S2则有
V
1
S
2
>
V
2
S
1
V1S2>V2S1
V1S2>V2S1
我们枚举性价比较小的宝石,假设性价比小的是s1,我们找一个S1和S2的最小公倍数lcm。然后这个宝石的个数必然是小于
l
c
m
/
s
1
lcm/s1
lcm/s1的,因为如果等于它,那么我们就可以将这些宝石换成性价比更高的s2宝石。然后我们保证s1宝石的总体积不超过宝箱的总体积即可。
AC代码:
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
ll gcd(ll a, ll b)
{
ll res=1;
while(b)
{
res = a;
a=b;
b=res%b;
}
return a;
}
ll _lcm(ll a, ll b)
{
return a*b/gcd(a,b);
}
void solve(int index)
{
ll n,s1,v1,s2,v2;
cin >>n>>s1>>v1>>s2>>v2;
if(v1*s2<v2*s1)
{
swap(v1,v2);
swap(s1,s2);
}
ll lcm = _lcm(s1,s2);
ll ans=0;
for(int i = 0;i < lcm/s2&&i*s2<=n;i++)
{
ans=max(ans,i*v2+(n-i*s2)/s1*v1);
}
cout <<ans<<endl;
}
int main()
{
int t;
scanf("%d",&t);
for(int i = 1; i <= t; i++)
{
cout <<"Case #"<<i<<": ";
solve(i);
}
return 0;
}
I Revenge of Fibonacci(trie树+数学基础)
题目地址Revenge of Fibonacci
题目大意:T组测试样例,问你一个数字串是哪个斐波那契数列的前缀,要求下标要最小
思路:参考HDU4099-Revenge of Fibonacci(trie树+数学基础)
先算斐波那契数,因为数字较大,所以要用大数模板,考虑到询问的数字串最多为40个,所以在插入trie树时可以选择插入<=40个,这样可以节省很大的内存。好吧,字典树我还不会做,后面补一下。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 7000000;
const int INF = 1e8;
int ch[maxn][10];
int val[maxn];
int cnt;
char c[200];
char str[200];
void add(char a[],char b[],char back[]){
int i=strlen(a)-1,j=strlen(b)-1,k=0;
int x,y,z;
int up=0;
while(i>=0||j>=0)
{
if(i<0)x=0;
else x=a[i]-'0';
if(j<0)y=0;
else y=b[j]-'0';
z=x+y+up;
c[k++]=z%10+'0';
up=z/10;
i--;
j--;
}
if(up>0)c[k++]=up+'0';
for(i=0;i<k;i++)back[i]=c[k-1-i];
back[k]='\0';
}
int getIdx(char a){
return a-'0';
}
void insert(char st[],int d){
int u = 0;
for(int i = 0; i < strlen(st) && i < 42; i++){
int k = getIdx(st[i]);
if(!ch[u][k]){
val[cnt] = d;
ch[u][k] = cnt++;
memset(ch[cnt],0,sizeof ch[cnt]);
}
u = ch[u][k];
}
}
int query(char st[]){
int u = 0;
for(int i = 0; i < strlen(st); i++){
int k = getIdx(st[i]);
if(!ch[u][k]){
return -1;
}
u = ch[u][k];
}
return val[u];
}
void init(){
cnt = 1;
memset(ch[0],0,sizeof ch[0]);
for(int i = 0; i < maxn; i++)
val[i] = INF;
char a[200],b[200],ans[200];
a[0] = '1',a[1] = 0;
b[0] = '1',b[1] = 0;
insert(a,0);
for(int i = 2; i < 100000; i++){
if(strlen(b) > 70){
a[strlen(a)-1] = 0;
b[strlen(b)-1] = 0;
}
add(a,b,ans);
insert(ans,i);
strcpy(a,b);
strcpy(b,ans);
}
}
int main(){
init();
int ncase,T=1;
cin >> ncase;
while(ncase--){
cin >> str;
printf("Case #%d: %d\n",T++,query(str));
}
return 0;
}