noip模拟54[碰巧]
noip模拟54 solutions
今天好像也还好,波波说这个是人家考过的挺难的题,但是人家有好多切掉的
我们啥也不是,害
T1 选择
这个好像和独立集很像啊,不过根本不是。。。
这个题说白了是个废题,因为这个算法不可以推广到一般情况,比如菊花图
主要是利用一个点的度数不超过10,这个地方可以状压
每一颗子树内都只有一个点可以向上走,因为向上的路径只有一条
所以我们可以记录有那些点可以
对于每一个节点我们统计经过它的路径的贡献,最后全部节点都加起来就行了
一个节点最多有10个儿子,我们可以状压来得到这些儿子最大的贡献
还可以判断一下,去掉某一个儿子之后会不会有影响,如果没有,那这个儿子的可以向上走的儿子,也可以是当前点的
AC_code
#include<bits/stdc++.h>
using namespace std;
#define re int
const int N=1005;
inline int read()
{
int ss=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
return cit?ss:-ss;
}
int n,m,ans;
int to[N*2],nxt[N*2],head[N],rp;
void add_edg(int x,int y){
to[++rp]=y;
nxt[rp]=head[x];
head[x]=rp;
}
int sca[N][N];
vector<int> fre[N];
int dp[(1<<10)+5];
int ji[15],cnt;
void dfs(int x,int f){
for(re i=head[x],y;i;i=nxt[i]){
y=to[i];
if(y==f)continue;
dfs(y,x);
}
cnt=0;for(re i=head[x];i;i=nxt[i])if(to[i]!=f)ji[++cnt]=to[i];
memset(dp,0,sizeof(dp));
for(re i=1;i<=cnt;i++)
for(re k=0;k<fre[ji[i]].size();k++){
for(re j=i+1;j<=cnt;j++)
for(re o=0;o<fre[ji[j]].size();o++)
if(sca[fre[ji[i]][k]][fre[ji[j]][o]]){
dp[(1<<i-1)|(1<<j-1)]=1;break;
}
if(sca[fre[ji[i]][k]][x])dp[(1<<i-1)]=1;
}
int S=(1<<cnt)-1;
for(re s=1;s<=S;s++)
for(re t=s;t;t=(t-1)&s)
dp[s]=max(dp[s],dp[t]+dp[s^t]);
ans+=dp[S];
for(re i=1;i<=cnt;i++)
if(dp[S^(1<<i-1)]==dp[S])
for(re j=0;j<fre[ji[i]].size();j++)
fre[x].push_back(fre[ji[i]][j]);
fre[x].push_back(x);
}
void file(){freopen("select.in","r",stdin);freopen("select.out","w",stdout);}
signed main(){
file();
//scanf("%d",&n);
n=read();
for(re i=1,x,y;i<n;i++){
//scanf("%d%d",&x,&y);
x=read(),y=read(),
add_edg(x,y),add_edg(y,x);
}
//scanf("%d",&m);
m=read();
for(re i=1,x,y;i<=m;i++){
//scanf("%d%d",&x,&y);
x=read(),y=read(),
sca[x][y]=1,sca[y][x]=1;
}
dfs(1,0);printf("%d",ans);
}
表格
最简单的式子应该都有了,官方题解也讲了
就是讨论六种情况,
不对,官方题解啥都讲了,直接上代码吧,就是拉格郎日插值法
注意边界
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
const int mod=1e9+7;
inline int ksm(int x,int y){
int ret=1;x%=mod;
while(y){
if(y&1)ret=ret*x%mod;
x=x*x%mod;y>>=1;
}
return ret;
}
inline int XLT(int n,int *x,int *y,int xi)
{ int ans=0;
for(int i=0,s1=1,s2=1;i<=n;++i){
s1=1;s2=1;
for(int j=0;j<=n;++j)
if(i!=j)s1=s1*(((xi-x[j])%mod+mod)%mod)%mod,s2=s2*(((x[i]-x[j])%mod+mod)%mod)%mod;
ans=(ans+y[i]%mod*s1%mod*ksm(s2,mod-2)%mod)%mod;
}
return (ans+mod)%mod;
}
int n,m,L,R;
int ggx[10],ggy[10],h1x[10],h1y[10],h2x[10],h2y[10];
// inline int g(int x){return (x%mod-2+mod)%mod*(m%mod-x%mod+mod+1)%mod;}
// inline int f(int x){return (x%mod-2+mod)%mod*(n%mod-x%mod+mod+1)%mod;}
inline int g(int x){return (x-2)%mod*((m-x+1)%mod)%mod;}
inline int f(int x){return (x-2)%mod*((n-x+1)%mod)%mod;}
inline int gg(int x){return XLT(3,ggx,ggy,x);}
inline int h1(int x){return XLT(6,h1x,h1y,x);}
inline int h2(int x){return XLT(3,h2x,h2y,x);}
void get_gg(){
fo(i,0,3){
ggx[i]=i+3;ggy[i]=0;
fo(j,3,i+3)ggy[i]=(ggy[i]+g(j))%mod;
}return ;
}
void get_h1(){
fo(i,0,6){
h1x[i]=i+3;h1y[i]=0;
fo(j,3,i+3)h1y[i]=(h1y[i]+f(j)*gg(R/2+2-j)%mod)%mod;
}return ;
}
void get_h2(){
fo(i,0,3){
h2x[i]=i+3;h2y[i]=0;
fo(j,3,i+3)h2y[i]=(h2y[i]+f(j)*gg(m)%mod)%mod;
}return ;
}
signed main(){
freopen("table.in","r",stdin);
freopen("table.out","w",stdout);
scanf("%lld%lld%lld%lld",&n,&m,&L,&R);
get_gg();get_h1();get_h2();
int val=0,var=0;
if(R/2+2-m-1>=3)var=(h1(min(n,R/2-1))-h1(R/2+2-m-1)+mod+h2(R/2+2-m-1))%mod;
else if(R/2-1>=3)var=h1(min(n,max(R/2-1,0ll)));
else var=0;
if(R/2+2-m-1>=min(n,R/2-1))var=h2(min(n,R/2-1));
R=L-1;get_gg();get_h1();get_h2();
if(R/2+2-m-1>=3)val=(h1(min(n,R/2-1))-h1(R/2+2-m-1)+mod+h2(R/2+2-m-1))%mod;
else if(R/2-1>=3)val=h1(min(n,max(R/2-1,0ll)));
else val=0;
if(R/2+2-m-1>=min(n,R/2-1))val=h2(min(n,R/2-1));
//cout<<var<<" "<<val<<endl;
printf("%lld",(var-val+mod)%mod*6%mod);
}
黑白
好像是和博弈论有那么点关系,我不会SG函数,所以先沽
啊我会了,直接上代码
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
const int N=105;
const int mod=998244353;
int n,a[N],b[N],ma,mb;
int f[N][N][N*2],p[N][N*2],dp[N][N*2];
int jc[N*10],inv[N*10];
int ksm(int x,int y){
int ret=1;
while(y){
if(y&1)ret=ret*x%mod;
x=x*x%mod;y>>=1;
}return ret;
}
int C(int x,int y){return jc[x]*inv[y]%mod*inv[x-y]%mod;}
signed main(){
freopen("black.in","r",stdin);
freopen("black.out","w",stdout);
scanf("%lld",&n);
fo(i,1,n)scanf("%lld",&a[i]),mb=max(mb,a[i]);
fo(i,1,n)scanf("%lld",&b[i]),ma=max(ma,b[i]);
fo(i,0,ma)f[i][0][i]=1;
fo(i,0,ma)
fo(j,0,mb)
fo(k,0,i+j)
fo(o,0,ma-i)(f[i+o][j+1][o+(o>=k)]+=f[i][j][k])%=mod;//cout<<i<<" "<<j<<" "<<k<<" "<<o<<" "<<f[i][j][k]<<endl;
//cout<<f[1][1][0]<<" "<<f[1][1][2]<<endl;
jc[0]=1;fo(i,1,1000)jc[i]=jc[i-1]*i%mod;
inv[0]=1;inv[1000]=ksm(jc[1000],mod-2);
fu(i,1000-1,1)inv[i]=inv[i+1]*(i+1)%mod;
fo(i,1,n)fo(j,0,ma+mb)p[i][j]=f[b[i]][a[i]][j]*ksm(C(a[i]+b[i],a[i]),mod-2)%mod;//cout<<C(a[i]+b[i],a[i])<<endl;
dp[0][0]=1;
fo(i,0,n-1){
fo(j,0,ma+mb){
if(!dp[i][j])continue;
fo(k,0,ma+mb){
dp[i+1][j^k]=(dp[i+1][j^k]+dp[i][j]*p[i+1][k])%mod;
}
}
}
printf("%lld",(1+mod-dp[n][0])%mod);
}
打怪
这个我好像不会处理要先杀哪个,然后直接把攻击×生命最大的干掉了,80pts
其实斜率优化一下就行了,好像是要用到CDQ的,也可以正反各一边
但是我只走了一边,注意统计答案时,用的是原来序列中的顺序,仔细读代码
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define re register int
const int N=3e5+5;
int n,b;
int nwv,nwt,ans,res;
int fro[N],beh[N];
struct node{
int a,d,t,e,id;
long double v;
node(){}
}sca[N];
int sta[N],top;
bool comp1(node x,node y){return x.v>y.v;}
bool comp2(node x,node y){return x.t!=y.t?x.t<y.t:x.e>y.e;}
double get(int x,int y){return 1.0*(sca[y].e-sca[x].e)/(sca[y].t-sca[x].t);}
int sol(int x,int y){
if(sca[x].id<sca[y].id)return sca[x].e+sca[y].e-sca[x].t*sca[y].a;
else return sca[x].e+sca[y].e-sca[y].t*sca[x].a;
}
signed main(){
freopen("fittest.in","r",stdin);
freopen("fittest.out","w",stdout);
scanf("%lld%lld",&n,&b);
for(re i=1;i<=n;i++){
scanf("%lld%lld",&sca[i].a,&sca[i].d);
sca[i].t=(sca[i].d-1)/b+1;
sca[i].v=1.0*sca[i].a/sca[i].t;
}
sort(sca+1,sca+n+1,comp1);
for(re i=1;i<=n;i++)fro[i]=fro[i-1]+sca[i].t;
for(re i=n;i>=1;i--)beh[i]=beh[i+1]+sca[i].a;
for(re i=1;i<=n;i++){
sca[i].e=fro[i]*sca[i].a-sca[i].a+beh[i+1]*sca[i].t;
sca[i].id=i;
nwt+=sca[i].t;ans+=nwt*sca[i].a-sca[i].a;
}
sort(sca+1,sca+n+1,comp2);
for(re i=1;i<n;i++){
if(sca[i].t!=sca[i-1].t){
while(top>1&&get(sta[top-1],sta[top])<get(sta[top],i))top--;
sta[++top]=i;
}
int l=1,r=top,mid;
while(l<r){
mid=l+r+1>>1;
if(sca[i+1].a<=get(sta[mid-1],sta[mid]))l=mid;
else r=mid-1;
}
res=max(res,sol(sta[l],i+1));
}
printf("%lld",ans-res);
}
QQ:2953174821