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
#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
#define ll long long using namespace std; int n; ll ans=0; int num[40000007]; int len=0; vector 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<
数三角 (几何)
时间限制: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
#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
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∈Hai;而 牛可乐得分为 \sum_{i\in T} b_i∑i∈Tbi。
牛牛和 牛可乐都希望自己的得分尽量比对方大。
你需要求出两人都使用最优策略的情况下,最终分别会选择哪些物品,若有多种答案或输出顺序,输出任意一种。
输入描述:
第一行,一个正整数 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
也会被判定为正确
题解: 看似 局部最优,实则整体最优 ->整体贪心
最终状态:两人分别拿固定数目物品,即约一半,
假设物品已经被选完,此时 牛牛选择的物品 A 属性的价值和是 N , 牛可乐选择的物品 B 属性价值和是 M 。
如果 牛牛的 (a1,b1)物品与 牛可乐的 (a2,b2)交换,则 N′=N−a1+a2,M′=M+b1−b2,对于 牛牛(目标是最大化 N−M )来说会变得更优仅当 a1+b1
N−MN化简就能得到),对于 牛可乐也一样。所以两人都会优先选择 ai+bi最大的物品。 将物品按照两个属性的和从大到小排序,依次分给两人即可。
除排序时间复杂度 O(n)。
#include
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
判正误
时间限制: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
#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
#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]); }