zoukankan      html  css  js  c++  java
  • 2019/8/29 校内模拟赛 考试报告

    A.准备(preparing.in)

    已知(p)为大于(2)的质数,从(1...2p)中选择(p)个数,使得这(p)个数的和能被(p)整除,求总方案数.

    思路1:((ple 30))

    动态规划打表.

    #include<bits/stdc++.h>
    
    long long Ans[]={0,0,0,8,0,52,0,492,0,0,0,64132,0,800048,0,0,0,137270956,0,1860277044,0,0,0,357975249028,0,0,0,0,0,1036802293087624,0};
    int n,x;
    
    int main()
    {
    	freopen("preparing.in","r",stdin);
    	freopen("preparing.out","w",stdout);
    	std::cin>>n;
    	while(n--)
    	{
    		std::cin>>x;
    		std::cout<<Ans[x]<<std::endl;
    	}
    	return 0;
    }
    

    思路2:((ple 1000))

    我们先排除掉选择(1...p)和选择(p+1...2p)这两种情况,剩下((dbinom{p}{2p}-2))种情况.

    那么问题转化为在({1,2,...,p-1,p})中选(k)个数((1le k < p)),在({p+1,p+2,...,2p-1,2p})中选((p-k))个数,两组中选的数之和能被(p)整除的方案数.

    容易发现,({1,2,...,p-1,p})({p+1,p+2,...,2p-1,2p})这两组数在模(p)意义下是相同的,不妨先讨论其中一组.

    假设我们在第一组中选了(k)个数,记为({a_1,a_2,...,a_k}).

    我们把所有可以表示为({(a_1+d)mod p,(a_2+d)mod p,...(a_k+d)mod p})的选法归为一,其中(d in[0,p-1]),那么每一类中,选择的数的和对(p)的余数为(0)的选法占了(1/p),对(p)的余数为(1)的选法占了(1/p),...,对(p)的余数为((p-1))的选法占了(1/p).

    由此可以推出,在第一组中选(k)个的所有选法中,和对(p)的余数为(0)的占(1/p),对(p)的余数为(1)的选法占(1/p),...,对(p)的余数为((p-1))的占(1/ p).这是因为,虽然我们并不知道的个数,但每一类中的每个余数的选法的占比是不变的,都是(1/p).

    现在我们考虑枚举第一组中选出的(k)个数的和对(p)的余数.

    假设是(0),占第一组总选法的(1/p),那么第二组中选出的(p-k)个数的和对(p)的余数也必须是(0),占第二组总选法的(1/p),由于在第一组和第二组里选数是两个独立事件,所以上述情况中合法选法占两组总选法的(dfrac{1}{p^2}).

    假设是(1),占第一组总选法的(1/p),那么第二组中选出的(p-k)个数的和对(p)的余数必须是(p- 1),占第二组总选法的(1/p),由于在第一组和第二组里选数是两个独立事件,所以上述情况中合法选法占两组总选法的(dfrac{1}{p^2}).

    ...

    假设是(p-1),占第一组总选法的(1/p),那么第二组中选出的(p-k)个数的和对(p)的余数必须是(1),占第二组总选法的(1/p),由于在第一组和第二组里选数是两个独立事件,所以上述情况中合法选法占两组总选法的(dfrac{1}{p^2}).

    那么在第一组中选了(k)个数,在第二组中选((p-k))个数的合法选法占总选法的比例为(dfrac{1}{p^2} imes p=1/p).

    容易发现,当(k)变化时,上述思路可以推广.

    那么在((dbinom{p}{2p}-2))种情况中,合法选法占(1/p).

    再加上最开始暂时排除的两种情况,总方案数为:

    [dfrac{dbinom{p}{2p}-2}{p}+2 ]

    B.奖学金(scholarship.cpp)

    [USACO 2004 Mar]Financial Aid 赞助学费

    [TJOI2013]奖学金

    首先将学生按成绩由小到大排序,考虑枚举中位数.

    值得注意的是,本题答案不具有二分性质,不能二分,但我考试的时候二分竟然有70分,数据实在是太水了.

    预处理(L(i))表示学生([1,i))中花费最小的(lfloordfrac{n}2 floor)个学生的总花费,(R(i))同理.

    那么从左到右扫描,寻找满足(L(i)+R(i)+cost(i)le F)的最靠右的学生,它的成绩即为答案.

    #include<bits/stdc++.h>
    const int SIZE=200005,INF=10005;
    int n,C,F,L[SIZE],R[SIZE];
    
    struct Stu
    {
    	int S,x;
    	bool operator <(const Stu &u)const
    	{
    		return S<u.S;
    	}
    }stu[SIZE];
    std::priority_queue<int>q;
    
    int main()
    {
    	scanf("%d%d%d",&n,&C,&F);
    	n/=2;
    	for(int i=1;i<=C;i++)
    		scanf("%d%d",&stu[i].S,&stu[i].x);
    	std::sort(stu+1,stu+1+C);
    	int sum=0;
    	for(int i=1;i<=n;i++)
    	{
    		sum+=stu[i].x;
    		q.push(stu[i].x);
    	}
    	for(int i=n+1;i<=C;i++)
    	{
    		L[i]=sum;
    		if(q.top()>stu[i].x)
    		{
    			sum-=q.top();
    			q.pop();
    			q.push(stu[i].x);
    			sum+=stu[i].x;
    		}
    	}
    	while(q.size())q.pop();
    	sum=0;
    	for(int i=C;i>=C-n+1;i--)
    	{
    		sum+=stu[i].x;
    		q.push(stu[i].x);		
    	}
    	for(int i=C-n;i;i--)
    	{
    		R[i]=sum;
    		if(q.top()>stu[i].x)
    		{
    			sum-=q.top();
    			q.pop();
    			q.push(stu[i].x);
    			sum+=stu[i].x;			
    		}
    	}	
    	int Ans=-1;
    	for(int i=n+1;i<=C-n;i++)
    	{
    		if(L[i]+R[i]+stu[i].x<=F)Ans=stu[i].S;
    	}
    	printf("%d",Ans);
    	return 0;
    }
    

    C.巧克力(chocolate.cpp)

    CF633F

    给定一颗点权无根树,求两条不相交的链的权值和的最大值.

    神仙DP题.

    在参考了很多份题解之后,终于懂了是如何DP的.

    我们以任意节点为根,DFS,维护以下四个值:

    (Long(x))表示(x)到它的子树中的最远叶子的距离,换句话说,就是经过(x),并且可以向上继续拓展的最长链.

    (DP1(x))表示(x)子树中最长的一条链的长度.

    (DP2(x))表示(x)子树中最长的两条不相交链的长度和.

    (DP3(x))表示(x)子树中一条链和另一条(x)到某个叶子的链的最大长度和,换句话说,就是一条链和另一条可以继续向上扩展的链的最大长度和.

    在转移时,讨论各个值所有可能的产生情况,取最优解进行转移.

    关于怎么转移,我还有很多绝妙的想法,但现在时间不够了,我不能把它们写下来

    #include<bits/stdc++.h>
    #define LL long long
    #define IL inline
    
    const int SIZE=200005;
    int head[SIZE],nex[SIZE],ver[SIZE],Tot;
    LL weight[SIZE];
    
    LL DP1[SIZE];//子树中选一条链的最大长度
    LL DP2[SIZE];//子树中选两条链的最大长度和 
    LL DP3[SIZE];//子树中选一条链和另一条到叶子节点的链的最大长度和
    LL Long[SIZE];//到叶子节点的链的最大长度
    
    void Link(int u,int v)
    {
    	nex[++Tot]=head[u];head[u]=Tot;ver[Tot]=v;
    	nex[++Tot]=head[v];head[v]=Tot;ver[Tot]=u;
    }
    
    IL LL m2(LL A,LL B){return A>B?A:B;}
    IL LL m3(LL A,LL B,LL C){return m2(A,B)>C?m2(A,B):C;}
    IL LL m4(LL A,LL B,LL C,LL D){return m3(A,B,C)>D?m3(A,B,C):D;}
    IL LL m5(LL A,LL B,LL C,LL D,LL E){return m4(A,B,C,D)>E?m4(A,B,C,D):E;}
    
    void DFS(int u,int F)
    {
    	Long[u]=weight[u];
    	DP1[u]=weight[u];
    	LL o=0;
    	for(int i=head[u];i;i=nex[i])
    	{
    		int v=ver[i];
    		if(v==F)continue;
    		DFS(v,u);
    		LL Tem1=DP1[u],Tem3=DP3[u];
    		DP1[u]=m3(DP1[u],DP1[v],Long[u]+Long[v]);
    		DP2[u]=m5(DP2[u],DP2[v],Long[u]+DP3[v],Long[v]+Tem3,Tem1+DP1[v]);
    		DP3[u]=m4(DP3[u],DP3[v]+weight[u],o+(weight[u]+Long[v]),Long[u]+DP1[v]);
    		Long[u]=m2(Long[u],Long[v]+weight[u]);
    		o=m2(o,DP1[v]);
    	} 
    }
    
    int main()
    {
    	std::ios::sync_with_stdio(false); 
    	int n,u,v;
    	std::cin>>n;
    	for(int i=1;i<=n;i++)std::cin>>weight[i];
    	for(int i=1;i<n;i++){std::cin>>u>>v;Link(u,v);}
    	DFS(1,0);
    	std::cout<<DP2[1];
    	return 0;
    }
    
  • 相关阅读:
    Xamarin图表开发基础教程(4)OxyPlot框架
    搜索页面scroll下拉时候进行刷新,显示更多搜索值
    搜索功能
    父组件操作子组件中的值,将父组件的值设置给子组件
    扩展music-list.vue让列表前三名显示🏆奖杯
    Scroll的使用
    Vue-lazyload的使用
    获取歌曲的播放时长
    audio音乐播放
    歌曲播放页面的数据vuex管理
  • 原文地址:https://www.cnblogs.com/TaylorSwift13/p/11431673.html
Copyright © 2011-2022 走看看