B
https://ac.nowcoder.com/acm/contest/3003/C
思路:
一开始不懂概率模意义下的运算,然后学了一波,例如原来是二分之一乘以二分之一,那么乘起来就是四分之一,那么模意义下也是直接相乘,但是记得模,然后就是1-二分之一,变成模的意义下就是mod-模意义下的概率+1;
接下来就是本题重点,dp
恰好有k个题目过范围大的话一个一个枚举就会爆掉,所以dp意义下,我们设dp【i】【j】意义是
i道题目恰好j道题过的概率;
显然
f[0][j] ={1,j=0;
{0,j>0;
x显然
f[i][j] ={f[i-1][j]*(1-pi),j=0;
{f[i-1][j-1]*pi+f[i-1][j]*(1-pi),j>0;
#include#define maxn 2020 using namespace std; typedef long long ll; const int mod=1000000007; int n,a[maxn]; ll dp[maxn][maxn]; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); dp[0][0]=1; for(int i=1;i<=n;i++){ dp[i][0]=(dp[i-1][0]*(mod-a[i]+1))%mod; for(int j=1;j<=i;j++) dp[i][j]=((dp[i-1][j]*(mod-a[i]+1)%mod)+(dp[i-1][j-1]*a[i]%mod))%mod; } // double ans=0; for(int i=0;i<=n;i++) cout<
给出坐标,求能构成多少个锐角三角形
我刚开始的时候想的是枚举钝角和直角
然后计算每三个点能组成的三角形的个数
减去共线的,再减去钝角和直角的个数,即为答案
而且我在极角排序之后,我试图用二分来确定上下界
这样也不是不能做,但是比较麻烦
题解的方法就比较好
统计锐角的个数,设为 AA,钝角和直角的个数,设为 BB
每个锐角三角形有三个锐角,每个钝角和直角三角形均贡献两个锐角
所以答案即为 A−2B3
#includeusing namespace std; typedef long long ll; const double pi=acos(-1.0); const double eps=1e-9; int n; struct node1 { double x,y; }a[2010]; double node[4010]; int main() { while(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;i++)scanf("%lf%lf",&a[i].x,&a[i].y); ll ans1=0,ans2=0; for(int i=1;i<=n;i++) { int cnt=0; for(int j=1;j<=n;j++) { if(i==j)continue; node[++cnt]=atan2(a[i].y-a[j].y,a[i].x-a[j].x); if(node[cnt]<0)node[cnt]+=2*pi; } sort(node+1,node+1+cnt); for(int j=1;j<=cnt;j++)node[j+cnt]=node[j]+2*pi; int l=1,r=1,len=1; for(int j=1;j<=cnt;j++) { while(r<=2*cnt&&node[r]-node[j]
求有多少个钝角三角形
#includeusing namespace std; typedef long long ll; const double pi=acos(-1.0); const double eps=1e-9; int n; struct node1 { double x,y; }a[2010]; double node[4010]; int main() { while(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;i++)scanf("%lf%lf",&a[i].x,&a[i].y); ll ans1=0,ans2=0; for(int i=1;i<=n;i++) { int cnt=0; for(int j=1;j<=n;j++) { if(i==j)continue; node[++cnt]=atan2(a[i].y-a[j].y,a[i].x-a[j].x); if(node[cnt]<0)node[cnt]+=2*pi; } sort(node+1,node+1+cnt); for(int j=1;j<=cnt;j++)node[j+cnt]=node[j]+2*pi; int l=1,r=1,len=1; for(int j=1;j<=cnt;j++) { while(r<=2*cnt&&node[r]-node[j]
链接:https://ac.nowcoder.com/acm/contest/3003/E
两边平方,就成了i+j+2根号ij=k,那么就是要使ij为完全平方数,也就是可以被根号出整数
#includeusing namespace std; typedef long long ll; int main() { ll n; scanf("%lld",&n); ll ans=0; for(ll i=1;i*i<=n;i++){ ll x=i*i; for(ll j=1;j*j<=x;j++){ if(x%j==0){ ans++; if(j*j!=x)ans++; } } } printf("%lld\n",ans); return 0; }
https://ac.nowcoder.com/acm/contest/3003/F
切勿被最优策略给骗了,说是最优,这样看你拿了这个物品,这个物品的ai和bi都到你手上了,你的模板是和对方拉分最大,所以实际上bi这个分数他拿不了了
用人话说你每次拿了一个物品计分ai但同时也剥夺了他拿bi的机会们,也就是拉分了ai+bi,故可以以ai+bi为排序
#include#define maxn 200010 using namespace std; int n; struct Node{ int posA,posB; }a[maxn]; struct New{ int key,pos; }b[maxn]; bool cmp(New x,New y){ return x.pos>y.pos; } int main(){ scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i].posA); for(int i=1;i<=n;++i){ scanf("%d",&a[i].posB); b[i].pos=a[i].posA+a[i].posB; b[i].key=i; } sort(b+1,b+n+1,cmp); for(int i=1;i<=n;++i) if(i&1) printf("%d ",b[i].key); printf("\n"); for(int i=1;i<=n;++i) if(!(i&1)) printf("%d ",b[i].key); return 0; }
H
思路:直接
用f[i]表示前ii个元素以ii为尾划分段后的最小值
也就是f[i]可以作为前面的一段的末尾,或者和前面的k-1个构成新的一段k,
#include#define maxn 200010 using namespace std; int n; struct Node{ int posA,posB; }a[maxn]; struct New{ int key,pos; }b[maxn]; bool cmp(New x,New y){ return x.pos>y.pos; } int main(){ scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i].posA); for(int i=1;i<=n;++i){ scanf("%d",&a[i].posB); b[i].pos=a[i].posA+a[i].posB; b[i].key=i; } sort(b+1,b+n+1,cmp); for(int i=1;i<=n;++i) if(i&1) printf("%d ",b[i].key); printf("\n"); for(int i=1;i<=n;++i) if(!(i&1)) printf("%d ",b[i].key); return 0; }