1005: ( Stupid Tower Defense )
由题意我们很明显可以知道,红色的塔放在最后面是最优的。
假如前i个塔,放j个绿塔,i-j个蓝塔。那么无论前i个塔的顺序怎么放,对后面的塔造成的影响是完全相同的。
dp[i][j]:前i个塔,放j个绿塔,能获得的最大价值。
dp[i][j]=max(dp[i-1][j-1]+当前塔放绿塔获得的能量值,dp[i-1][j]+当前塔放蓝塔获得的能量值);
#include <iostream>
#include<stdio.h>
#include<vector>
#include<queue>
#include<stack>
#include<string.h>
#include<algorithm>
using namespace std;
#define LL __int64
#define lcm(a,b) (a*b/gcd(a,b))
LL intx(LL num,LL t,LL x,LL chi)
{
return num*t*(x+chi);
}
LL inty(LL num,LL t,LL y,LL chi)
{
return (t)*y*(num-1)*num/2+chi*t*num;
}
LL intz(LL num,LL t,LL z,LL chi)
{
return chi*(num*t+(num-1)*num/2*z);
}
LL dp[1501][1501];
int main()
{
LL n,x,y,z,t,cas,i,j;
scanf("%I64d",&cas);
LL nn = 1;
while(cas--)
{
scanf("%I64d%I64d%I64d%I64d%I64d",&n,&x,&y,&z,&t);
LL ans = t*x*n;
LL sum;
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
{
dp[i][0]=dp[i-1][0];
ans=max(ans,dp[i][0]+intx(n-i,t+i*z,x,0));
for(int j=1;j<=i-1;j++)
{
dp[i][j]=max(dp[i-1][j-1]+inty(1,t+z*(i-j),y,(j-1)*y),
dp[i-1][j]+intz(1,t+z*(i-1-j),z,j*y));
ans=max(ans,dp[i][j]+intx(n-i,t+(i-j)*z,x,j*y));
}
dp[i][i]=dp[i-1][i-1]+inty(1,t,y,(i-1)*y);
ans=max(ans,dp[i][i]+intx(n-i,t,x,i*y));
}
printf("Case #%I64d: %I64d\n",nn++,ans);
}
return 0;
}
1007: ( Magical Forest )
反正各种离散化,然后标记本行原先属于那一行,之后乱七八糟的搞一下就可以了。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <assert.h>
#include<iostream>
#include<vector>
using namespace std;
#define MAXN 10050
#define LL __int64
vector<int>vecx,vecxx;
vector<int>vecy,vecyy;
struct list
{
int x;
int y;
int c;
friend bool operator <(const list &a,const list &b)
{
if(a.x!=b.x)return a.x<b.x;
else return a.y<b.y;
}
}node[110000];
int fx[110000];
int fy[110000];
int k;
int find(int x,int leap)
{
// cout<<x<<" "<<leap<<endl;
if(leap==0)
{
int l=0;
int r=vecx.size();
int mid=(l+r)/2;
while(l<r)
{
//cout<<l<<" "<<r<<" "<<mid<<" "<<vecx[mid]<<endl;
if(vecx[mid]<x)l=mid+1;
else r=mid;
mid=(l+r)/2;
}
if(mid!=vecx.size()&&vecx[mid]==x)return mid+1;
else return 0;
}
if(leap==1)
{
int l=0;
int r=vecy.size();
int mid=(l+r)/2;
while(l<r)
{
if(vecy[mid]<x)l=mid+1;
else r=mid;
mid=(l+r)/2;
}
if(mid!=vecy.size()&&vecy[mid]==x)return mid+1;
else return 0;
}
return 0;
}
void out(int x,int y)
{
// cout<<x<<" -- "<<y<<endl;
if(x==0||y==0)
{
cout<<"0"<<endl;
return;
}
int l=1;
int r=k+1;
int mid=(l+r)/2;
while(l<r)
{
if(node[mid].x<x)l=mid+1;
else if(node[mid].x>x)r=mid;
else if(node[mid].x==x)
{
if(node[mid].y<y)l=mid+1;
else if(node[mid].y>=y)r=mid;
}
mid=(l+r)/2;
}
if(node[mid].y==y&&node[mid].x==x&&mid<=k)
{
cout<<node[mid].c<<endl;
}
else cout<<"0"<<endl;
}
int main()
{
int W,cas;
int n,m;
scanf("%d",&W);
cas=0;
while(W--)
{
cas++;
scanf("%d%d%d",&n,&m,&k);
vecx.clear();
vecxx.clear();
vecy.clear();
vecyy.clear();
fx[0]=fy[0]=0;
for(int i=1;i<=k;i++)
{
fx[i]=i;
fy[i]=i;
scanf("%d%d%d",&node[i].x,&node[i].y,&node[i].c);
vecxx.push_back(node[i].x);
vecyy.push_back(node[i].y);
}
sort(vecxx.begin(),vecxx.end());
sort(vecyy.begin(),vecyy.end());
vecx.push_back(vecxx[0]);
vecy.push_back(vecyy[0]);
for(int i=1;i<k;i++)
{
if(vecxx[i]!=vecxx[i-1])vecx.push_back(vecxx[i]);
if(vecyy[i]!=vecyy[i-1])vecy.push_back(vecyy[i]);
}
for(int i=1;i<=k;i++)
{
node[i].x=find(node[i].x,0);
node[i].y=find(node[i].y,1);
}
sort(node+1,node+k+1);
printf("Case #%d:\n",cas);
int q,x,a,b;
scanf("%d",&q);
while(q--)
{
scanf("%d%d%d",&x,&a,&b);
if(x==1)
{
a=find(a,0);
b=find(b,0);
swap(fx[a],fx[b]);
}
if(x==2)
{
a=find(a,1);
b=find(b,1);
swap(fy[a],fy[b]);
}
if(x==3)
{
a=find(a,0);
b=find(b,1);
out(fx[a],fy[b]);
}
}
}
return 0;
}
1010:FSF’s game
由题意我们可以知道,对于任意一对长为n,宽为m的长方形,我们可以得到的分数为:
假如gcd(n,m)=2^x*3^y.....,.假如d为n的因子
(N,M)=n*m/(gcd(n,m))*(2^0+2^1+..+2^x)*(3^0+3^1+...+3^y);
很明显当n固定时,在m等于1~n的时候,m/(gcd(n,m))*(2^0+2^1+..+2^x)*(3^0+3^1+...+3^y)的总和等于所有的d*(d+1)/2的总和
那就可以预处理一个数因子的总和,然后直接递推式就好。
#include <iostream>
#include<stdio.h>
#include<vector>
#include<queue>
#include<stack>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxn 550000
#define UI unsigned int
#define N 550000
#define LL __int64
UI ans[maxn];
UI use[maxn];
void mk()
{
memset(use,0,sizeof(use));
for(UI i=1;i<maxn;i++)
{
LL now=(LL)i*((LL)i+(LL)1)/(LL)2;
UI add=now;
for(UI j=i;j<maxn;j+=i)
{
use[j]=use[j]+add;
}
}
}
void init()
{
mk();
ans[1]=1;
for(UI i=2;i<maxn;i++)
{
ans[i]=ans[i-1]+use[i]*(UI)i;
}
}
int main()
{
int T,n;
init();
scanf("%d",&T);
int cas=0;
while(T--)
{
cas++;
scanf("%d",&n);
printf("Case #%d: %u\n",cas,ans[n]);
}
return 0;
}