ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【水题选做】一些简单的数学题

2022-05-05 19:01:31  阅读:166  来源: 互联网

标签:frac 水题 sum db 简单 数学题 include data dp


P1487失落的成绩单

题意

就是一个\(n\)项数列\(A\)满足\(A_i=\frac{A_{i-1}-A_{i+1}}{2}+d\),给出\(A_1\)和\(A_n\),求某一项\(A_m\)的值。

思路

这个式子看起来很好,可惜并不能找到很好的性质,也没有几何意义啥的。

然后我们把它移个项,整理一下,\(A_{i+1}+2A_i-A_{i-1}=2d\)

这是一个常系数线性递推方程,解下特征方程就知道两个特征根分别是\(x=-1\pm\sqrt{2}\),特解也很好求,瞪眼法就知道是\(A_i=d\)

然后\(A_i\)的通解可以表示为\(C_1*(-1+\sqrt{2})^n+C_2*(-1-\sqrt{2})^n+d\)

代入两个点值,把\(C_1\)和\(C_2\)解出来就结束了。

这题的坑点在于\(m\)可能\(=0\),要特判输出\(0\)。

代码

点击查看代码
#include<cstdio>
#include<cstdlib>
#include<cmath>
#define db double
using namespace std;
int main(){
    int n,m,i,j;
    db d,A1,An;
    db C1,C2;
    db k1,k2,k3,k4,b1,b2;
    scanf("%d%d",&n,&m);
    scanf("%lf%lf%lf",&d,&A1,&An);
    if(m==0){
        printf("0.000");
        return 0;
    }
    k1=sqrt(2)-1,k2=-1-sqrt(2);
    k3=pow(k1,n),k4=pow(k2,n);
    b1=A1-d,b2=An-d;
    C2=(b2*k1-b1*k3)/(k1*k4-k2*k3);
    C1=(b1-C2*k2)/k1;
    db ans=C1*pow(k1,m)+C2*pow(k2,m)+d;
    printf("%.3lf",ans);
    // system("pause");
    return 0;
}

P1409 骰子

题意

\(n\)个人排成一排,你排在第\(m\)个。

每轮队首的人投一次骰子。

\(\frac{1}{6}\)的概率,队首的人获胜。
\(\frac{1}{2}\)的概率,队首的人排到队尾。
\(\frac{1}{3}\)的概率,队首的人出队。

若队列中仅剩一人,则该人获胜,求你获胜的概率。

思路

数据范围\(n\leq 1000\),看起来就很像一个\(\Theta(n^2)\)的概率DP。

设\(i\)个人排第\(j\)个赢的概率为\(dp[i][j]\),那么当\(j>1\)时有\(dp[i][j]=\frac{1}{2} dp[i][j-1]+\frac{1}{3}dp[i-1][j-1]\)。

\(j==1\)时有\(dp[i][1]=\frac{1}{6}+\frac{1}{2}dp[i][i]\)。

我们直接把dp[i][i]当成未知量,这样每个值就可以用\(k_1dp[i][i]+k_2\)表示,到最后会得到一个关于\(dp[i][i]\)的一元一次方程。

解出\(dp[i][i]\),再代回\(dp[i][1]...dp[i][i-1]\),就得到了\(n==i\)时一整行的结果。

输出\(dp[n][m]\)即可。为了实现方便,我直接把数对\(k_1,k_2\)存到dp数组里。

代码

点击查看代码
#include<cstdio>
#include<cstdlib>
#define db double
#define maxn 1010
using namespace std;
struct data{
    db x,y;
    data(){x=y=0;}
    data(db t1,db t2){
        x=t1;y=t2;
    }
    data operator *(db t){
        return data(t*x,t*y);
    }
    data operator +(data t){
        return data(x+t.x,y+t.y);
    }
} dp[maxn][maxn];
int main(){
    int i,j,n,m;
    db tmp;
    scanf("%d%d",&n,&m);
    dp[1][1]=data(0,1);
    for(i=2;i<=n;++i){
        dp[i][1]=data(0.5,1.0/6.0);
        for(j=2;j<=i;++j){
            dp[i][j]=dp[i][j-1]*(1.0/2.0)+dp[i-1][j-1]*(1.0/3.0);
        }
        tmp=dp[i][i].y/(1-dp[i][i].x);
        dp[i][i]=data(0,tmp);
        for(j=1;j<i;++j){
            db t1,t2;
            t1=dp[i][j].x;t2=dp[i][j].y;
            dp[i][j]=data(0,t1*tmp+t2);
        }
    }
    printf("%.9lf",dp[n][m].y);
    // system("pause");
    return 0;
}

P6028算术

题意

算了太长了不想写-_-

思路

显然这个连乘式需要化简。

\[\prod_{i=1}^{k}\frac{p_i^{a_i+1}-1}{p_i^{a_i+1}-p_i^{a_i}}=\prod_{i-1}^{k}\frac{1-\frac{1}{p_i^{a_i+1}}}{1-\frac{1}{p_i}}=\prod_{i=1}^k\sum_{j=0}^{a_i}\frac{1}{p_i^j} \]

观察一下这个东西,对于每个质因子枚举次幂,很像是在枚举因数。我们再乘个\(n\)发现式子就变成了因数之和。(把连乘号跟求和号展开写就很明显了)

所以\(f(n)=\frac{\sigma_1(n)}{n}\),其中\(\sigma_1(n)=\sum_{d|n} d\),这个式子就很简洁了,但为了求前缀和,我们还是写开。

\(f(n)=\frac{1}{n}\sum_{d|n}d\),\(\sum_{i=1}^n f(n)=\sum_{i=1}^{n}\frac{1}{i}\sum_{d|i} d\)

根据套路,枚举因数变为枚举倍数:

\[\sum_{i=1}^nf(n)=\sum_{d=1}^nd\sum_{i=1}^{\lfloor\frac{n}{i}\rfloor}\frac{1}{id}=\sum_{d=1}^n\sum_{i=1}^{\lfloor\frac{n}{i}\rfloor}\frac{1}{i} \]

注意这个$$\sum_{i=1}^{\lfloor\frac{n}{i}\rfloor}\frac{1}{i}$$

整除分块的形式已经很明显了,因为对于一长串的\(d\),内层求和号的结果不变。

令\(H(n)=\sum_{i=1}^{n}\frac{1}{i}\)

这个东西是调和级数的部分和,在\(n\)很大的时候有很好的近似\(H(n)\approx ln(n)+\gamma\),\(\gamma=0.57722\)是欧拉常数。

数据小的时候可以预处理,这样\(H(x)\)就可以\(O(1)\)求解,算上整除分块,时间复杂度为\(O(\sqrt n)\)。

代码

点击查看代码
#include<cstdio>
#include<cstdlib>
#include<cmath>
#define db long double
#define ll long long
#define gamma 0.57722
using namespace std;
db f[10000010]={0};
db F(ll n){
    if(n<=10000000) return f[n];
    else return log(n)+gamma;
}
int main(){
    int i,j;
    ll l,r,n;
    db ans=0;
    for(i=1;i<=10000000;++i) f[i]=f[i-1]+(db)1.0/(db)i;
    scanf("%lld",&n);
    for(l=1,r=1;l<=r;l=r+1,r=n/(n/l)){
        ans+=(r-l+1)*F(n/l);
        if(r>=n) break;
    }
    printf("%.10Lf",ans);
    // system("pause");
    return 0;
}

标签:frac,水题,sum,db,简单,数学题,include,data,dp
来源: https://www.cnblogs.com/landmine-sweeper/p/16225929.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有