2020牛客寒假算法基础集训营2 (期望dp,数论,几何、模数、DP)

C. 算概率  (期望DP)

链接:https://ac.nowcoder.com/acm/contest/3003/C
来源:牛客网
 

算概率

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

牛牛刚刚考完了期末,尽管 牛牛 做答了所有 n\text{}nn 道题目,但他不知道有多少题是正确的。
不过,牛牛 知道第 i\text{}ii 道题的正确率是 pip_ipi​。
牛牛 想知道这 n 题里恰好有 0,1,…,n0,1,\dots,n0,1,…,n 题正确的概率分别是多少,对 109+710^9+7109+7 取模。
对 109+710^9+7109+7 取模的含义是:对于一个 b≠0b\neq 0b​=0 的不可约分数 aba\over bba​,存在 q\text{}qq 使得 b×q mod (109+7)=ab\times q \bmod (10^9+7) =ab×qmod(109+7)=a,q\text{}qq 即为 aba\over bba​ 对 109+710^9+7109+7 取模的结果。

输入描述:

第一行,一个正整数 n\text{}nn 。
第二行,n\text{}nn 个整数 p1,p2,…,pnp_1,p_2,\dots,p_np1​,p2​,…,pn​,在模 109+710^9+7109+7 意义下给出。
保证 1≤n≤20001\leq n\leq 20001≤n≤2000。

输出描述:

输出一行 n+1\text{}n+1n+1 个用空格隔开的整数表示答案(对 109+710^9+7109+7 取模)。

示例1

输入

复制1 500000004

1
500000004

输出

复制500000004 500000004

500000004 500000004

说明

 

有 1 道题,做对的概率是 121 \over 221​ ( 121 \over 221​ 在模 109+710^9+7109+7 意义下为 500000004 )。

题解:

转移方程:dp[i][j] = ( dp[i-1][j-1] * p[i] ) + ( dp[i-1][j] * (1-p[i]+mod) );

前 i 道题 对 j 道的概率 

= 前 i-1 道题 对 j-1 道的概率 * p[i] + 前 i-1 道题 对 j 道的概率 * (1-p[i])

#include<bits/stdc++.h>
#define ll long long 

using namespace std;
ll mod=1e9+7;
int n;
int p[2004];
ll dp[2004][2004];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&p[i]);
	}
	dp[0][0]=1;
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<=i;j++)
		{
			if(j==0)
			{
				dp[i][j]=dp[i-1][j]*(1-p[i]+mod)%mod;
				continue;
			}
			dp[i][j]=(dp[i-1][j-1]*p[i])%mod+(dp[i-1][j]*(1-p[i]+mod))%mod;
			dp[i][j]%=mod;
		}
	}
	for(int i=0;i<=n;i++)
	{
		printf("%lld ",dp[n][i]);
	}
}

E. 做计数  (数论)

链接:https://ac.nowcoder.com/acm/contest/3003/E
来源:牛客网
 

做计数

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

这一天,牛牛与 牛魔王相遇了――然而这并不在 牛牛期望之中。
 牛魔王不出意料又给 牛牛一道看似很难的题目:求有多少个不同的正整数三元组 (i,j,k)\text{}(i,j,k)(i,j,k) 满足 i+j=k\sqrt i+\sqrt j=\sqrt ki​+j​=k​,且 i×j≤ni\times j\leq ni×j≤n。

牛牛并不会做,你能略施援手吗?

当两个三元组 (i1,j1,k1),(i2,j2,k2)\text{}(i_1,j_1,k_1), (i_2,j_2,k_2)(i1​,j1​,k1​),(i2​,j2​,k2​) 满足 i1≠i2i_1\neq i_2i1​​=i2​ 或 j1≠j2j_1\neq j_2j1​​=j2​ 或 k1≠k2k_1\neq k_2k1​​=k2​ 时它们被认为是不同的。

输入描述:

第一行,一个正整数 n。

保证 1≤n≤4×1071\leq n\leq 4\times 10^71≤n≤4×107。

输出描述:

输出一行,一个整数表示答案。

示例1

输入

复制1

1

输出

复制1

1

说明

(1,1,4)

作者:Ycrpro
链接:https://ac.nowcoder.com/discuss/364961
来源:牛客网
 

+=   左右平方  i+2+j=k   

则i*j 必定为完全平方数 ,枚举小于n的所有完全平方数ii,再枚举每个完全平方数ii的 a*b==ii 因数组合 ,a的枚举范围为 sqrt(ii) ,

枚举ii O( sqrt(n) )   枚举a O( sqrt(n) )   总复杂度O(n)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n;
ll ans=0;
int num[40000007];
int len=0;
vector<int> V;
int main()
{
	scanf("%d",&n);
	ll ans=0;
	int ii=sqrt(n);

	for(int i=1;i*i<=n;i++)
	{
		int ii=i*i;
		for(int j=1;j*j<=ii;j++)
		{
			if(j*j==ii) ans++;
			else if(ii%j==0)ans+=2;
		}		
	}
	cout<<ans<<endl;
	
	
}

数三角 (几何)

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述 

牛牛得到了一个平面,这个平面上有 n 个不重合的点,第 i 个点的坐标为 (x_i,y_i)(xi​,yi​)。

牛牛想知道,这 n 个不重合的点形成的三角形中,总共有多少个钝角三角形。

输入描述:

第一行,一个正整数 n,表示点数。

第二行至第 n+1 行中,第 i+1 行包含两个整数 x_i,y_ixi​,yi​,表示第 i 个点的坐标。

保证 1\leq n\leq 5001≤n≤500,-10^4\leq x_i,y_i\leq 10^4−104≤xi​,yi​≤104。

输出描述:

输出一行,一个整数表示答案。

示例1

输入

复制

3
0 0
-1145 1
1 0

输出

复制

1

题解:暴力枚举所有点组合 ,向量积判断是否为钝角 且 不共线

#include<bits/stdc++.h>
#define pi acos(-1)
using namespace std;
int n;
double x[505],y[505];
int pd(int i,int j,int k)
{
	
	return (x[j]-x[i])*(x[k]-x[i])+(y[j]-y[i])*(y[k]-y[i])<0&&(x[j]-x[i])*(y[k]-y[i])!=(x[k]-x[i])*(y[j]-y[i]);
    
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
      scanf("%lf%lf",&x[i+1],&y[i+1]);
    }
    long long ans=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            if(j==i) continue;
            for(int k=j+1;k<=n;k++)
            {
                
                if(pd(i,j,k)==1||pd(j,i,k)||pd(k,i,j)) ans++;
            }
        }
    }
	printf("%lld\n",ans);
}

F. 拿物品  (贪心)

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld

题目描述 

牛牛和 牛可乐 面前有 n 个物品,这些物品编号为 1,2,\dots,n1,2,…,n ,每个物品有两个属性 a_i, b_iai​,bi​ 。

牛牛与 牛可乐会轮流从剩下物品中任意拿走一个, 牛牛先选取。

设 牛牛选取的物品编号集合为 H,牛可乐选取的物品编号的集合为 T,取完之后,牛牛 得分为 \sum_{i\in H} a_i∑i∈H​ai​;而 牛可乐得分为 \sum_{i\in T} b_i∑i∈T​bi​。

牛牛和 牛可乐都希望自己的得分尽量比对方大。

你需要求出两人都使用最优策略的情况下,最终分别会选择哪些物品,若有多种答案或输出顺序,输出任意一种。

输入描述:

第一行,一个正整数 n,表示物品个数。
第二行,n 个整数 a_1,a_2,\dots,a_na1​,a2​,…,an​,表示 n 个物品的 A 属性。
第三行,n 个整数 b_1,b_2,\dots,b_nb1​,b2​,…,bn​,表示 n 个物品的 B 属性。
保证 2\leq n\leq 2\times 10^52≤n≤2×105,0\leq a_i,b_i\leq 10^90≤ai​,bi​≤109。

输出描述:

输出两行,分别表示在最优策略下 牛牛和 牛可乐各选择了哪些物品,输出物品编号。

示例1

输入

复制

3
8 7 6
5 4 2

输出

复制

1 3
2

说明

 

3 1

2

也会被判定为正确

题解: 看似 局部最优,实则整体最优    ->整体贪心 

最终状态:两人分别拿固定数目物品,即约一半,

假设物品已经被选完,此时 牛牛选择的物品 AAA 属性的价值和是 NNN , 牛可乐选择的物品 BBB 属性价值和是 MMM 。

如果 牛牛的 (a1,b1)物品与 牛可乐的 (a2,b2)交换,则 N′=N−a1+a2,M′=M+b1−b2,对于 牛牛(目标是最大化 N−M )来说会变得更优仅当 a1+b1<a2+b2( N′−M′>N−MN化简就能得到),对于 牛可乐也一样。所以两人都会优先选择 ai+bi最大的物品。

将物品按照两个属性的和从大到小排序,依次分给两人即可。

除排序时间复杂度 O(n)。

#include<bits/stdc++.h>
using namespace std;
int n;
struct node
{
	int v,id; 
}a[200005];
bool cmp(node & a,node &b)
{
	return a.v>b.v;
}

int main()
{
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		int v;
		scanf("%d",&v);
		a[i].v=v;
		a[i].id=i+1;
	}
	for(int i=0;i<n;i++)
	{
		int v;
		scanf("%d",&v);	
		a[i].v+=v;
	}
	sort(a,a+n,cmp);
	for(int i=0;i<n;i+=2)
	{
		printf("%d ",a[i].id);
	}
	printf("\n");
	for(int i=1;i<n;i+=2)
	{
		printf("%d ",a[i].id);
	}
}

判正误

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述 

牛可乐有七个整数 \text{}a,b,c,d,e,f,ga,b,c,d,e,f,g 并且他猜想 a^d+b^e+c^f=gad+be+cf=g。但  牛可乐无法进行如此庞大的计算。
请验证 牛可乐的猜想是否成立。

输入描述:

第一行一个正整数 T,表示有 T 组数据。
每组数据输入一行七个整数 \text{}a,b,c,d,e,f,ga,b,c,d,e,f,g 。
保证 1\leq T \leq 10001≤T≤1000 , -10^9\leq a,b,c,g\leq 10^9−109≤a,b,c,g≤109 , 0\leq d,e,f\leq 10^90≤d,e,f≤109 保证不会出现指数和底数同为 0 的情况。

输出描述:

每组数据输出一行,若猜想成立,输出 Yes ,否则输出 No。

示例1

输入

复制

2
1 1 4 5 1 4 258
114514 1919810 1 2 3 4 1

输出

复制

Yes
No

说明

 

1e9+7 1e9+9

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll mod[4];
ll a,b,c,d,e,f,g;
ll ksm(ll aa,ll bb,ll mod)
{
    ll ans=1;
    while(bb)
    {
        if(bb%2) ans*=aa;
        ans%=mod;
        aa*=aa;
        aa%=mod;
        bb/=2;
    }
    return ans;
}
int main()
{
    int T;
mod[0]=1e9+7;
mod[1]=1e9+9;
mod[2]=1e9+13;
mod[3]=1e9+17;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld%lld%lld%lld%lld%lld",&a,&b,&c,&d,&e,&f,&g);
        int ans=0;
        for(int j=0;j<2;j++)
        {
             
            ll sum=0;
            sum+=ksm(a,d,mod[j]);
             
            sum%=mod[j];
            sum+=ksm(b,e,mod[j]);
            sum%=mod[j];
            sum+=ksm(c,f,mod[j]);
            sum%=mod[j];
             
            if(sum==(g)) ans++;
        }
        if(ans==2) printf("Yes\n");
        else printf("No\n");
    }
}

施魔法

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述 

牛可乐有 n 个元素( 编号 1..n ),第 i 个元素的能量值为 a_iai​。
牛可乐可以选择至少 k 个元素来施放一次魔法,魔法消耗的魔力是这些元素能量值的极差。形式化地,若所用元素编号集合为 S,则消耗的魔力为 \max_{i\in S}\{a_i\}-\min_{i\in S}\{a_i\}maxi∈S​{ai​}−mini∈S​{ai​}。

牛可乐要求每个元素必须被使用恰好一次
牛可乐想知道他最少需要多少魔力才能用完所有元素,请你告诉他。

输入描述:

第一行两个正整数 \text{}n, kn,k 。

第二行 n 个整数 a_1,a_2,\dots,a_na1​,a2​,…,an​。

保证 1\leq k\leq n\leq 3\times 10^51≤k≤n≤3×105,0\leq a_i\leq 10^90≤ai​≤109。

输出描述:

输出一行,一个整数表示答案。

示例1

输入

复制

4 2
8 7 114514 114513

输出

复制

2

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,k;
int a[300005];
ll dp[300005];
int main()
{
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	sort(a+1,a+n+1);
	for(int i=0;i<=n;i++)
	{
		dp[i]=1e18;
	}
	ll minn=-a[1];
	for(int i=k;i<=n;i++)
	{
		minn=min(minn,dp[i-k]-a[i-k+1]);
		dp[i]=minn+a[i];
	}
	printf("%lld\n",dp[n]);
}
发布了44 篇原创文章 · 获赞 6 · 访问量 1156

猜你喜欢

转载自blog.csdn.net/qq_43868883/article/details/104209123