A
二分加贪心
code:
class KingdomAndTrees {
public:
int n;
bool judge(const int x,vector<int>heights)
{
int las=0;
for(int i=0;i<n;i++)
{
int now=heights[i];
if(now<=las)
{
if(now+x<=las) return false;
las++;
}
else las=max(now-x,las+1);
}
return true;
}
int minLevel(vector<int> heights) {
n=heights.size();
int l=0,r=inf;
while(l<=r)
{
int mid=((ll)l+r)>>1;
if(judge(mid,heights)) r=mid-1;
else l=mid+1;
}
return r+1;
}
};
B
算出g[i]表示剩余能用的数中,比b中的i个数大的有多少个,用zero表示a中0的数量
获胜概率
p=sum/(n∗n)
,
sum=∑ni=1∑nj=1[ai>bj]
最小化(p-0.5)
f[i][j]表示前i个g[i],使得sum=j,至少用多少个0,dp,得出哪些sum是可行的
code:
const long double eps = 1e-10;
class KingdomAndDice {
public:
int n,al;
int a[maxn],b[maxn],c[maxn];
int f[110][maxn];
inline void down(int &x,const int &y){if(x==-1||x>y)x=y;}
double newFairness(vector<int> firstDie, vector<int> secondDie, int X) {
n=firstDie.size();
for(int i=0;i<n;i++) a[i]=firstDie[i],b[i]=secondDie[i];
sort(a,a+n); sort(b,b+n);
al=n*n;
int now=0,zero=0;
for(int i=0;i<n;i++) if(!a[i]) zero++;
for(int i=0;i<n;i++) if(a[i])
for(int j=0;j<n;j++) if(a[i]>b[j]) now++;
b[n]=X+1; c[0]=zero;
for(int i=0;i<n;i++)
{
c[i+1]=b[i+1]-b[i]-1;
for(int j=0;j<n;j++) if(b[i]<a[j]&&a[j]<b[i+1]) c[i+1]--;
}
memset(f,-1,sizeof f); f[0][now]=0;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=al;j++) if(f[i-1][j]!=-1)
for(int k=0;k<=c[i]&&j+i*k<=al;k++) down(f[i][j+i*k],f[i-1][j]+k);
}
int re=al; double p=(double)re/al;
for(int i=al;i>=0;i--) if(f[n][i]!=-1&&f[n][i]<=zero)
if(fabs((double)i/al-0.5)-fabs(p-0.5)<=eps) re=i,p=(double)re/al;
return p;
}
};
C
比较恶心的讨论,细节挺多的
求n个点m条边编号前K个点度数为2的联通无向图有多少种
用E[i]=i*(i-1)/2表示i个点的完全图边数,f[i][j]表示i个点j条边的无向连通图数量,用所有情况减不连通的数量算得f
于是K=0的情况就是f[n][m]
当K=1时,从原图中去掉这个点,可能剩下1或2个联通块,枚举点n所在联通块计算
当K=2时,若这两个点之间有边,大致与K=1时相同,若无边,去掉这两个点,可能剩下1/2/3个联通块,同样枚举点n的联通块,与点n不同联通块的最大编号点u联通块,计算答案
code:
#define ll long long
#define maxn 55
#define maxm 1300
#define __ %=Mod
using namespace std;
const ll Mod = 1e9+7;
class KingdomAndCities {
public:
int E[maxn];
ll C[maxm][maxm],f[maxn][maxm];
void pre()
{
for(int i=1;i<maxn;i++) E[i]=i*(i-1)>>1;
int u=E[50];
for(int i=0;i<=u;i++)
{
C[i][0]=1ll;
for(int j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%Mod;
}
f[1][0]=1ll;
for(int i=2;i<=50;i++) for(int j=i-1,uj=min(E[i],50);j<=uj;j++)
{
f[i][j]=C[E[i]][j];
for(int a=1;a<i;a++) for(int b=a-1,ub=min(j,E[a]);b<=ub;b++)
(f[i][j]-=C[i-1][a-1]*f[a][b]%Mod*C[E[i-a]][j-b]%Mod)__;
(f[i][j]+=Mod)__;
}
}
int howMany(int N, int M, int K) {
pre();
if(!M) return (int)f[N][K];
ll re=0;
N-=M;
if(M==1)
{
if(N<=1||K<2) return (int)re;
K-=2;
re=f[N][K]*C[N][2]%Mod;
for(int a=1;a<N;a++)
{
for(int b=a-1,ub=min(E[a],K);b<=ub;b++)
(re+=f[a][b]*C[N-1][a-1]%Mod*a%Mod*f[N-a][K-b]%Mod*(N-a)%Mod)__;
}
}
if(M==2)
{
if(N<=0||K<3) return (int)re;
K-=3;
re=f[N][K]*N%Mod*N%Mod;
for(int a=1;a<N;a++)
{
for(int b=a-1,ub=min(E[a],K);b<=ub;b++)
(re+=C[N-1][a-1]*f[a][b]%Mod*f[N-a][K-b]%Mod*a%Mod*(N-a)*2ll%Mod)__;
}
K--; if(K<0) return (int)re;
(re+=f[N][K]*(C[N][2]*C[N][2]%Mod)%Mod)__;
for(int a=1;a<N;a++)
{
for(int b=a-1,ub=min(E[a],K);b<=ub;b++)
{
ll temp;
temp=C[N-1][a-1]*f[a][b]%Mod*f[N-a][K-b]%Mod;
(re+=temp*a*(N-a)%Mod*a*(N-a)%Mod)__;
(re+=2ll*temp%Mod*((ll)a*(N-a)*C[N-a][2]+(ll)(N-a)*a*C[a][2])%Mod)__;
}
}
ll t3=0;
for(int A=1;A<=N-2;A++) for(int B=1;A+B<N;B++)
{
int c=N-A-B;
ll tmp=C[N-1][A-1]*C[N-A-1][B-1]%Mod*(2ll*A*B*c*(A+B+c)%Mod)%Mod;
for(int a=A-1,ua=min(E[A],K);a<=ua;a++) for(int b=B-1,ub=min(E[B],K-a);b<=ub;b++)
(t3+=tmp*f[A][a]%Mod*f[B][b]%Mod*f[c][K-a-b]%Mod)__;
}
(re+=t3)__;
}
return (int)re;
}
};