zoukankan      html  css  js  c++  java
  • 2019.10.19考试解题报告

    2019.10.19考试解题报告

    总结

    期望得分:(60 + 30 + 0)
    实际得分:(30 + 40 + 0)

    又是没有相信自己的暴力,最后被自己的优化程序搞死的一天。

    (T1)写了(60)暴力,本来想要优化一下下,结果想写(O(n))的判断,却变成了(O(无穷))的超时。。(瞎搞失败)

    (T2)正解肯定是线段树,但是不会写(3)操作的东西,于是看到有(k=1)(k=2)的部分分,就去瞎搞,以为能得(30),没想到教师机跑的还挺快(可能是关了360的原因),拿了(40)(瞎搞成功)

    (T3)树形(DP),想写又不会写


    思路

    T1

    推式子

    T2

    考虑用线段树来完成此题。对于每个节点我们维护一个(f[i](i in [1, 10])),表示这个节点所对应区间选(i)个球的答案。
    考虑如何合并两个节点(lc,rc)(f[i] = sum(lc.f[j] * rc.f[i-j]) j in [0,i])
    对于取相反数操作,只有当(i)是奇数时,才会改变(f[i])的符号。
    对于一段区间(+c)的操作,设这段区间的长度为(len),则新的(f[i])(sum (f(j) * c^{i-j} * C(len - j, i - j)) jin [0,i]) 其中(C(n,m))表示(n)个数中选(m)个的组合数
    这样我们就可以套用区间修改区间询问的线段树来解决这道题了,时间复杂度为(O(c^2nlogn))

    T3

    做法((from solution)

    考虑用树形(dp)来解决这道问题。
    (f[i][j])表示在(i)的子树中(i)所在的连通块大小为(j),且其他连通块大小均符合要求的删边方案数
    对于每个点(i)我们一棵一棵地将其子树加进来,设新加入子树的根为(u)
    若删除(u)(i)之间的边,则用$f[i][j] * sum (f[u][s]) s in [k,n] (去更新)f[i][j]( 若不删)u(与)i(之间的边,则枚举)u(所在连通块的大小)s(,并更新)f[i][j+s]$
    时间复杂度 (O(n^3))
    考虑一个优化:每次新加一颗子树时,(j)只需枚举到前面已经加进来的子树大小之和,(s)也只需枚举到新子树的大小
    这只是一个常数优化?其实每个点对相当于只在(lca)处被算了一次
    故优化后的时间复杂度是(O(n^2))的,本题得以解决。


    代码

    T1

    #include <iostream>
    #include <cstdio>
    #include <set>
    using namespace std;
    const int N=200010;
    int n,m;
    long long a[N],GCD=0;
    set<long long> Set;
    long long gcd(long long a,long long b)
    {
    	return b?gcd(b,a%b):a;
    }
    long long qabs(long long x){return x<0?-x:x;}
    int main()
    {
    	freopen("ninja.in","r",stdin);
    	freopen("ninja.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    		scanf("%lld",&a[i]);
    	for(int i=2;i<=n;i++)
    		GCD=gcd(2LL*qabs(a[i]-a[1]),GCD);
    	if(GCD==0)GCD=1000000000LL*1000000000LL; 
    	Set.insert(0LL);
    	for(int i=1;i<=n;i++)
    		Set.insert(((2*a[i])%GCD+GCD)%GCD);
    	while(m--)
    	{
    		long long q;
    		scanf("%lld",&q);
    		if(Set.find((q%GCD+GCD)%GCD)!=Set.end())
    			puts("Yes");
    		else
    			puts("No");
    	}
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
    
    

    T2

    #include <cstdio>
    #include <cstdlib>
    #define MOD 1000000007
    #define N 100005
    typedef long long LL; 
    using namespace std;
    struct Node {
    	LL f[11];
    }node[N * 4];
    LL a[N], lazy1[N * 4];
    bool lazy2[N * 4];
    LL C[N][11];
    
    Node merge(Node lc, Node rc) {
    	Node o;
    	o.f[0] = 1;
    	for (int i = 1; i <= 10; i++) {
    		o.f[i] = 0;
    		for (int j = 0; j <= i; j++)
    			o.f[i] = (o.f[i] + lc.f[j] * rc.f[i - j] % MOD) % MOD;
    	}
    	return o;
    }
    
    void build(int o, int l, int r) {
    	if (l == r) {
    		for (int i = 0; i <= 10; i++) node[o].f[i] = 0;
    		node[o].f[0] = 1;
    		node[o].f[1] = (a[l] % MOD + MOD) % MOD;
    		return ;
    	}
    	int mid = (l + r) >> 1;
    	build(o * 2, l, mid);
    	build(o * 2 + 1, mid + 1, r);
    	node[o] = merge(node[o * 2], node[o * 2 + 1]);
    	return ;
    }
    
    void update1(int o, int l, int r, int c) {
    	int len = r - l + 1;
    	LL ff[11];
    	for (int i = 0; i <= 10; i++) ff[i] = node[o].f[i];
    	for (int i = 1; i <= 10; i++) {
    		node[o].f[i] = 0;
    		LL t = 1;
    		for (int j = 0; j <= i; j++) {
    			LL tmp = ff[i - j] * C[len - (i - j)][j] % MOD * t % MOD;
    			node[o].f[i] = (node[o].f[i] + tmp) % MOD;
    			t = t * c % MOD;
    		}
    	}
    	return ;
    }
    
    void push_down(int o, int l, int r) {
    	int mid = (l + r) >> 1;
    	if (lazy1[o]) {
    		if (lazy2[o * 2])
    			lazy1[o * 2] = (lazy1[o * 2] + MOD - lazy1[o]) % MOD;
    		else 
    			lazy1[o * 2] = (lazy1[o * 2] + lazy1[o]) % MOD;
    		if (lazy2[o * 2 + 1])
    			lazy1[o * 2 + 1] = (lazy1[o * 2 + 1] + MOD - lazy1[o]) % MOD;
    		else 
    			lazy1[o * 2 + 1] = (lazy1[o * 2 + 1] + lazy1[o]) % MOD;
    		update1(o * 2, l, mid, lazy1[o]);
    		update1(o * 2 + 1, mid + 1, r, lazy1[o]);
    		lazy1[o] = 0;
    	}
    	if (lazy2[o]) {
    		lazy2[o * 2] ^= 1;
    		lazy2[o * 2 + 1] ^= 1;
    		for (int j = 1; j <= 10; j += 2) {
    			node[o * 2].f[j] = MOD - node[o * 2].f[j];
    			node[o * 2 + 1].f[j] = MOD - node[o * 2 + 1].f[j];
    		}
    		lazy2[o] = 0;
    	}
    }
    
    void modify1(int o, int l, int r, int ll, int rr, int c) {
    	if (ll <= l && rr >= r) {
    		if (lazy2[o]) lazy1[o] = (lazy1[o] + MOD - c) % MOD;
    		else lazy1[o] = (lazy1[o] + c) % MOD;
    		update1(o, l, r, c);
    		return ;
    	}
    	int mid = (l + r) >> 1;
    	push_down(o, l, r);
    	if (ll <= mid) modify1(o * 2, l, mid, ll, rr, c);
    	if (rr > mid) modify1(o * 2 + 1, mid + 1, r, ll, rr, c);
    	node[o] = merge(node[o * 2], node[o * 2 + 1]);
    	return ;
    }
    
    void modify2(int o, int l, int r, int ll, int rr) {
    	if (ll <= l && rr >= r) {
    		for (int i = 1; i <= 10; i += 2) node[o].f[i] = MOD - node[o].f[i];
    		lazy2[o] ^= 1;
    		return ;
    	}
    	int mid = (l + r) >> 1;
    	push_down(o, l, r);
    	if (ll <= mid) modify2(o * 2, l, mid, ll, rr);
    	if (rr > mid) modify2(o * 2 + 1, mid + 1, r, ll, rr);
    	node[o] = merge(node[o * 2], node[o * 2 + 1]);
    	return ;
    }
    
    Node query(int o, int l, int r, int ll, int rr) {
    	if (ll <= l && rr >= r) 
    		return node[o];
    	int mid = (l + r) >> 1;
    	push_down(o, l, r);
    	if (rr <= mid) return query(o * 2, l, mid, ll, rr);
    	if (ll > mid) return query(o * 2 + 1, mid + 1, r, ll, rr);
    	Node lc = query(o * 2, l, mid, ll, rr);
    	Node rc = query(o * 2 + 1, mid + 1, r, ll, rr);
    	return merge(lc, rc);
    }
    
    int main(int argc, char ** argv) {
    	freopen("game.in", "r", stdin);
    	freopen("game.out", "w", stdout);
    	int n, m;
    	scanf("%d %d", &n, &m);
    	C[0][0] = 1;
    	for (int i = 1; i <= n; i++) {
    		C[i][0] = 1;
    		for (int j = 1; j <= 10; j++) 
    			C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD;
    	}
    	for (int i = 1; i <= n; i++) 
    		scanf("%d", &a[i]);
    	build(1, 1, n); 
    	for (int i = 1; i <= m; i++) {
    
    		int l, r, opt;
    		scanf("%d%d%d",&opt, &l, &r);
    		if (opt == 1) {
    			int c;
    			scanf("%d", &c);
    			c = (c % MOD + MOD) % MOD;
    			modify1(1, 1, n, l, r, c);
    		}
    		else if (opt == 2) {
    			modify2(1, 1, n, l, r);
    		}
    		else {
    			int k;
    			scanf("%d", &k);
    			Node o = query(1, 1, n, l, r);
    			printf("%d
    ", o.f[k] % MOD);
    		}
    	}
    	return 0;
    }
    
    

    T3

    #include<cstdio>
    #include<cstdlib>
    #define N 5555
    #define M 786433
    using namespace std;
    typedef long long LL;
    struct edge
    {
    	int t,n;
    }e[N*2];
    LL h[N],size[N],f[N][N],g[N],cnt[N];
    int n,K,tote;
    void add(int u,int v)
    {
    	e[++tote].t=v;
    	e[tote].n=h[u];
    	h[u]=tote;
    	return ;
    }
    void dfs(int u,int fa)
    {
    	size[u]++; f[u][1]=1;
    	for (int i=h[u];i;i=e[i].n)
    	{
    		int v=e[i].t;
    		if (v==fa) continue;
    		dfs(v,u);
    		for (int j=1;j<=size[u]+size[v];j++) g[j]=0;
    		for (int j=1;j<=size[u];j++) g[j]=cnt[v]*f[u][j]%M;
    		for (int j=1;j<=size[u];j++)
    		for (int k=1;k<=size[v];k++) g[j+k]=(g[j+k]+f[u][j]*f[v][k]%M)%M;
    		for (int j=1;j<=size[u]+size[v];j++) f[u][j]=g[j];
    		size[u]+=size[v];
    	}
    	for (int i=K;i<=size[u];i++) cnt[u]=(cnt[u]+f[u][i])%M;
    	return ;
    }
    int main()
    {
    	freopen("cut.in","r",stdin);
    	freopen("cut.out","w",stdout);
    	scanf("%d %d",&n,&K);
    	for (int i=1;i<n;i++)
    	{
    		int u,v;
    		scanf("%d %d",&u,&v);
    		add(u,v); add(v,u);
    	}
    	dfs(1,1);
    	printf("%d
    ",cnt[1]);
    	fclose(stdin);
        fclose(stdout);
    	return 0;
    }
    
    
  • 相关阅读:
    微服务定义及.Net Core中用的技术
    IPad分屏,当电脑第二显示屏
    .net Core1.0 邮件发送
    AutoMapper总结
    02-C#(基础)基本的定义和说明
    01-.Net编程机制
    C#基础篇--静态成员、抽象成员、接口
    C#基础篇--面向对象(类与对象)
    期末总结
    改动后的封装
  • 原文地址:https://www.cnblogs.com/loceaner/p/11705055.html
Copyright © 2011-2022 走看看