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;