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; }
2014多校联合-第七场
时间: 2024-11-08 06:03:19