2014多校联合-第七场

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值