Math(CC PARSIN)

    xiaoxiao2026-08-08  21

    题目大意

    给出m,n和一个两位小数x。 求 k[1]+k[2]+...+k[m]=nΠmi=1sin(k[i]x) n<=10^9,m<=30

    这题真的是道数学题

    首先考虑一个简单的dp 设f[i][j]表示 i=jl=1k[l] 时所有情况的和 容易想到一个简单的转移 f[i][j]=ik=1f[il][j1]sin(kx) 考虑当k[m]=1时对于f[n][m]的贡献为f[n-1][m-1]*sin(x) 当k[m]>1时呢 解数学题时间: 要用到几个常见的公式: sin(a+b)=sin(a)cos(b)+sin(b)*cos(a) cos(a+b)=cos(a)cos(b)-sin(a)sin(b) sin(a)^2+cos(a)^2=1 然后就可以手推了。。。 1sin(kx)=sin((k1)x+x)=sin((k2)x+2x) 122sin(kx)=sin((k1)x+x)+sin((k2)x+2x) 3sin((k1)x+x)=sin(x)cos((k1)x)+cos(x)sin((k1)x) 4sin((k2)x+2x)=2sin(x)cos(x)cos((k2)x)+(cos(x)2sin(x)2)sin((k2)x) =2sin(x)cos(x)cos((k2)x)+2cos(x)2sin((k2)x)+sin((k2)x) 5sin(x)cos((k1)x)=sin(x)cos((k2)x+x))=sin(x)(cos((k2)x)cos(x)sin((k2)x)sin(x)) 6cos(x)sin((k1)x)=cos(x)sin((k2)x+x)=cos(x)(sin(x)cos((k2)x)+cos(x)sin((k2)x)) 3,5,67sin((k1)x+x)=sin(x)cos((k1)x)+cos(x)sin((k1)x) =sin(x)(cos((k2)x)cos(x)sin((k2)x)sin(x))+cos(x)(sin(x)cos((k2)x)+cos(x)sin((k2)x)) =2sin(x)cos(x)cos((k2)x)+cos(x)2sin((k2)xsin(x)2sin((k2)x)) =2sin(x)cos(x)cos((k2)x)+2cos(x)2sin((k2)x)sin((k2)x) 2,4,782sin(kx)=sin((k1)x+x)+sin((k2)x+2x) =4sin(x)cos(x)cos((k2)x)+4cos(x)2sin((k2)x)+2sin((k2)x) 89sin(kx)=2sin(x)cos(x)cos((k2)x)+2cos(x)2sin((k2)x)+sin((k2)x) =2cos(x)(sin(x)cos((k2)x)+cos(x)sin((k2)x))+sin((k2)x)=2cos(x)sin((k1)x)+sin((k2)x) 终于,我们得到了一个不错的式子,通过这个式子可以发现k[m]>1时对f[n][m]的贡献为2cos(x)*f[n-1][m]+f[n-2][m] 然后就可以矩阵乘法了。 复杂度O(8*m^3log n)

    代码

    #include<cstring> #include<algorithm> #include<cstdio> #include<cmath> #define fo(i,a,b) for(i=a;i<=b;i++) const int maxn=60+5; int i,j,n,m,t,k; struct ar{ double a[maxn][maxn]; } a,c; double x; ar ch(ar a,ar b){ ar c; memset(c.a,0,sizeof(c.a)); fo(i,1,m*2) fo(j,1,m*2) fo(k,1,m*2) c.a[i][j]=c.a[i][j]+a.a[i][k]*b.a[k][j]; return c; } int main(){ scanf("%d",&t); while (t){ t--; scanf("%d%d%lf",&m,&n,&x); memset(a.a,0,sizeof(a.a)); memset(c.a,0,sizeof(c.a)); fo(i,m+1,m*2){ a.a[i][i-m]=1,a.a[i-m][i]=-1; a.a[i][i]=2*cos(x);if (i<m*2)a.a[i][i+1]=sin(x); } c.a[1][1]=sin(x);c.a[1][m+1]=sin(2*x);c.a[1][m+2]=sin(x)*sin(x); n--; while (n){ if (n%2)c=ch(c,a); a=ch(a,a); n/=2; } double s=c.a[1][m]; if (s>0) printf("+");else printf("-"); s=fabs(s); if (s<1){ double s1=0.1; while (1) if (s>s1) {printf("%d\n",(int)(s/s1));break;}else s1*=0.1; }else{ while (s)if (s<10) {printf("%d\n",(int)s);break;}else s/=10; } } }
    转载请注明原文地址: https://ju.6miu.com/read-1310982.html
    最新回复(0)