SRM 552 Div1

来源:互联网 发布:马刺热火第六场数据 编辑:程序博客网 时间:2024/05/21 20:27

250pts

答案就是min(Rn(n+1)/6,Gn(n+1)/6,Bn(n+1)/6,R+G+Bn(n+1)/2)

#include <bits/stdc++.h>using namespace std;#define ll long longclass FoxPaintingBalls{public:    ll theMax(ll R,ll G,ll B,int n)    {        ll t=(ll)n*(n+1)/2,t1=t/3;        ll ans=(R+G+B)/t;        if(t1)ans=min(min(R/t1,G/t1),min(ans,B/t1));        return ans;    }   };

500pts

分别按两个矩形上下分界和左右分界计算。
以左右分界为例,设L[i][j]表示第i列左边,两种花的个数差为j时两种花个数的最大和。R[i][j]表示第i列右边,两种花的个数差为j时两种花个数的最大和。然后枚举分界的列和左右的差。合并起来。
复杂度O(n5)

#include <bits/stdc++.h>using namespace std;int sum[31][31][2];int n,m,ans;int L[31][2100],R[31][2100];int SUM(int x,int y,int tp){    if(x<0||y<0)return 0;    return sum[x][y][tp];}int cal(int x1,int y1,int x2,int y2,int tp){return SUM(x2,y2,tp)+SUM(x1-1,y1-1,tp)-SUM(x1-1,y2,tp)-SUM(x2,y1-1,tp);}int get(int x1,int y1,int x2,int y2){return cal(x1,y1,x2,y2,0)-cal(x1,y1,x2,y2,1);}int get1(int x1,int y1,int x2,int y2){return cal(x1,y1,x2,y2,0)+cal(x1,y1,x2,y2,1);}void upd(int &x,int y){x=max(x,y);}void cal(int x){    for(int i=0;i<n;i++)        for(int j=1;j<m;j++)        {               sum[i][j][0]+=sum[i][j-1][0];            sum[i][j][1]+=sum[i][j-1][1];        }    for(int i=1;i<n;i++)        for(int j=0;j<m;j++)        {            sum[i][j][0]+=sum[i-1][j][0];            sum[i][j][1]+=sum[i-1][j][1];        }    memset(L,-1,sizeof(L));    memset(R,-1,sizeof(R));    for(int i=0;i<n;i++)        for(int j=i;j<n;j++)            upd(L[0][get(i,0,j,0)+n*m],get1(i,0,j,0));    for(int i=1;i<m;i++)    {        memcpy(L[i],L[i-1],sizeof(L[i]));        for(int j=0;j<n;j++)            for(int k=j;k<n;k++)                for(int t=0;t<=i;t++)                    upd(L[i][get(j,t,k,i)+n*m],get1(j,t,k,i));    }    for(int i=0;i<n;i++)        for(int j=i;j<n;j++)            upd(R[m-1][get(i,m-1,j,m-1)+n*m],get1(i,m-1,j,m-1));    for(int i=m-2;i>=0;i--)    {        memcpy(R[i],R[i+1],sizeof(R[i]));        for(int j=0;j<n;j++)            for(int k=j;k<n;k++)                for(int t=m-1;t>=i;t--)                    upd(R[i][get(j,i,k,t)+n*m],get1(j,i,k,t));    }    for(int i=-n*m;i<=n*m;i++)        for(int j=-n*m;j<=n*m;j++)            if(fabs(i+j)<=x)            {                for(int k=0;k<m-1;k++)                    if(L[k][i+n*m]!=-1&&R[k+1][j+n*m]!=-1)                        ans=max(ans,L[k][i+n*m]+R[k+1][j+n*m]);            }}class FoxAndFlowerShopDivOne{public:    int theMaxFlowers(vector<string>flo,int dif)    {        ans=-1;        n=flo.size();m=flo[0].size();        for(int i=0;i<n;i++)            for(int j=0;j<m;j++)            {                sum[i][j][0]=flo[i][j]=='L';                sum[i][j][1]=flo[i][j]=='P';            }        cal(dif);        for(int i=0;i<n;i++)            for(int j=0;j<m;j++)            {                sum[j][i][0]=flo[i][j]=='L';                sum[j][i][1]=flo[i][j]=='P';            }        swap(n,m);        cal(dif);        return ans;    }}cls;

900pts

先筛出maxDiff以内的素数。
设f[i][j]表示只用后i个素数可以得到的小于等于j的满足条件的数的个数。
那么f[i][j]=f[i+1][j]+f[i+1][jp[i]2k+1]
当p[i]*p[i]>j时答案由一个素数组成。可以直接二分出答案。
复杂度很迷。。。

#include <bits/stdc++.h>using namespace std;#define ll long long#define N 1100000#define M 41000000#define mod 1000007#define PA pair<int,ll>ll n;int p[N>>3],cnt;bool ip[N];ll find(int x,ll y){    if(x==cnt+1||y<p[x])return 1;    if((ll)p[x]*p[x]>=y)return upper_bound(p+1,p+1+cnt,y)-p-x+1;    ll ret=find(x+1,y);    for(ll i=p[x];i<=y;)    {        ret=ret+find(x+1,y/i);        if((i*=p[x])>y)break;        i*=p[x];    }    return ret; }class HolyNumbers{public:    ll count(ll bon,int mx)    {        n=bon;        for(int i=2;i<=mx;i++)        {            if(!ip[i])p[++cnt]=i;            for(int j=1;j<=cnt&&i*p[j]<=mx;j++)            {                ip[i*p[j]]=1;                if(i%p[j]==0)break;            }        }        return find(1,n);    }}cls;
0 0