zoukankan      html  css  js  c++  java
  • HNOI2018省队集训 Day3

    HNOI2018省队集训 Day3

    circular

    简单题

    直接破环为链+倍增即可。

    admirable

    最开始想的是点分治,因为往上的路径有点不好搞,觉得题解肯定还有复杂度更小的做法就去看题解

    然后发现可以处理出以某个儿子为根的f值,就可以直接dfs了,复杂度从(nlog^3)变成(n(log^2+sqrt n))。具体方法就是模拟一下多项式除以二项式再乘上一个二项式,同一size的儿子一起处理。

    然后开始写,写了一半要预处理NTT单位根

    #include<bits/stdc++.h>
    using namespace std;
    int read(){
    	int x=0,pos=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0;
    	for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    	return pos?x:-x;
    } 
    #define ll long long
    #define FOR(i,a,b) for(register int i=(a);i<=(b);++i)
    #define ROF(i,a,b) for(register int i=(a);i>=(b);--i)
    typedef vector<int> poly
    int n;
    const int N = 200001;
    const int mod = 998244353;
    struct node{
    	int v,nex;
    }edge[N*2];
    int head[N],top=0,sz[N],fa[N],deg[N];
    poly sv[N],pw[N];
    void add(int u,int v){
    	edge[++top].v=v;
    	edge[++top].nex=head[u];
    	head[u]=top;
    }
    void dft()
    poly operator *(const poly &a,const poly &b){
    	poly A=a,B=b;
    	int len=1;
    	while(len<A.size()+B.size()) len*=2;
    	init(len);
    	poly C(len,0);
    	dft(A,len,1);dft(B,len,1);
    	FOR(i,0,len-1) C[i]=1ll*A[i]*B[i]%mod;
    	
    }
    poly work(int l,int r){
    	if(l==r) return {1,sv[now][l]};
    	int mid=(l+r)>>1;
    	return work(l,mid)*work(r,mid);
    }
    void dfs1(int now,int pre){
    	sz[now]=1;fa[now]=pre;
    	for(int i=head[now];i;i=edge[i].nex){
    		int v=edge[i].v;
    		if(v==pre) continue;
    		dfs1(v,now);
    		sz[now]+=sz[v]; 
    		deg[now]++;
    		sv[now].push_back(sz[v]);
    	}
    	pw[now]=work(0,deg[now]-1);
    }
    int main(){
    	n=read();
    	FOR(i,1,n-1){
    		int u=read(),v=read();
    		add(u,v);add(v,u);
    	}
    	dfs1(1,0);
    	dfs2(1);
    }
    

    然后一看题目,模数1e9+9,噔 噔 咚(心肺停止)

    写nm

    考场上要么写n^2+链要么留到最后再淦吧

    illustrious

    打表神题

    首先打表得出 (f(i)) 是i的出现次数,那么我们算1e6个数就可以得出3e9的f

    然后 (f(n)) 的前缀和 (g(n)) 表示 (f(m) = n) 的最大的 m

    那么 (f(f(n))) 表示序列中下标为 (n) 处的数((f(n)) ) 的出现次数

    (g(f(n))) 表示序列中最大的是 (f(n)) 的位置。

    那么 (g(f(n)) − f(f(n))) 则表示序列中第一个等于 (f(n)) 的位置的前一个位置,即最后一个为 (f(n) − 1) 的位置,即 (g(f(n) − 1))

    然后考虑算 (g(g(n)))

    [egin{aligned} g(g(n))-g(g(n-1)) &=sum_{i=g(n-1)+1}^{g(n)} f(i) \ &=sum_{i=g(n-1)+1}^{g(n)} n \ &=n cdot f(n) end{aligned} ]

    所以 (g(g(n))=sum_{i=1}^{n} i cdot f(i))
    然后分段算一下

  • 相关阅读:
    从零开始学android开发-四大组件之一 Activity
    从零开始学android开发-详细谈谈intent的startActivityForResult()方法
    从零开始学android-一行两个按钮居中 布局
    nginx上用fastcgi配置python环境
    服务器程序源代码分析之三:gunicorn
    全面解读python web 程序的9种部署方式
    python检测文件是否更新
    nginx安装
    solr教程,值得刚接触搜索开发人员一看
    Shell标准输出、标准错误 >/dev/null 2>&1
  • 原文地址:https://www.cnblogs.com/lcyfrog/p/12979742.html
Copyright © 2011-2022 走看看