SRM 552 Div1

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 long
class 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值