ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

noip模拟54[碰巧]

2021-09-18 07:02:51  阅读:151  来源: 互联网

标签:node noip min int 54 h1 sca 碰巧 mod


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函数,所以先沽

打怪

这个我好像不会处理要先杀哪个,然后直接把攻击×生命最大的干掉了,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);
}

标签:node,noip,min,int,54,h1,sca,碰巧,mod
来源: https://www.cnblogs.com/hzoi-fengwu/p/15306992.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有