@description@

给出 n, m, x,你需要求出下列式子的值:

\[\sum_{(\sum_{i=1}^mk_i)=n}(\prod_{i=1}^{m}\sin(k_i*x))
\]

其中 ki 为正整数。由于答案非常大,你只需要输出答案(保证不为 0)的正负(如果是负数输出负号,否则输出正号)和从左往右第一个非 0 数位上的数字即可。

input

第一行一个整数 T 表示数据组数。

对于每组数据,每行有两个整数 m,n 和一个两位小数 x。

对于 100%的数据,T ≤ 10,n ≤ 10^9,m ≤ 30。

output

输出共 T 行,每行两个字符表示答案。

sample input

2

3 5 0.01

3 6 0.02

sample output

+2

+4

@solution@

其实题目要你求解的说白了就是卷积。即对于多项式 \(f(p) = \sum_{i=1}^{+\infty}\sin(i*x)p^i\),求 \(f^m(p)\) 中第 n 项的系数为多少。然而 n 最大可以为 10^9,FFT 再怎么优化也过不了。

我们发现对于这个卷积,我们想要得到的其实只有第 n 项的系数,其他项的系数并不重要,而 FFT 必然要求出所有的系数,所以时间复杂度肯定降不下来。我们不得不换一种思路。

如果是一般多项式,FFT 就是时间复杂度的下限。但是我们的系数是三角函数,也就是说,我们要利用三角函数的一些性质。

数据范围 n <= 10^9,且对象是三角函数。如果熟悉的话,很容易想到三角函数的递推式:

\[\sin kx = 2\cos x\sin(k-1)x -\sin(k-2)x
\]

边界为已知量 \(\sin 0, \sin x\)。 \(\cos x\) 是一个我们可以预先知道的常数,这样子就可以和矩阵乘法扯上关系了。

这个式子是怎么来的呢?可以参考下面的推导过程(但是如果你很熟悉了可以直接跳过)。

首先是三角函数的和差公式:

\[\sin kx = \sin x\cos (k-1)x+\cos x\sin (k-1)x
\]

这个式子中的 \(\cos (k-1)x\) 是我们想要消去的,因此再对它使用一次和差公式。

\[\sin kx =\sin x\cos(k-2)x\cos x-\sin^2 x\sin(k-2)x + \cos x\sin (k-1)x
\]

又出现了 \(\cos (k-2)x\)。但是,注意到其实可以把 \(\sin x\cos(k-2)x\) 当作一个整体,而这个整体出现在 \(\sin (k-1)x\) 的和差公式中。

因此,我们把 \(\sin (k-1)x = \sin x\cos (k-2)x+\cos x\sin (k-2)x\) 变形代入上式。

\[\sin kx =\cos x\sin(k-1)x -\cos^2 x\sin(k-2)x-\sin^2 x\sin(k-2)x + \cos x\sin (k-1)x
\]

恒等变形,就可以得到我们的结果:

\[\sin kx =2\cos x\sin(k-1)x -\sin(k-2)x
\]

好的我们推完式子再回到我们刚刚的思路。

考虑几种特殊情况吧。

当 m = 1 时,就是求 \(\sin nx\), 直接矩阵加速即可(当然最直接的还是暴力算)。

当 m = 2 时,令 \(g[i] = \sum_{j=1}^{i-1}(\sin(j*x)*\sin((i-j)*x))\),我们相当于是求 \(g[n]\)。

我们尝试建立递推关系。代入三角函数的递推式得到(注意边界情况的存在):

\[g[i] = \sin x*\sin((i-1)*x)+\sum_{j=2}^{i-1}((2\cos x\sin(j-1)x -\sin(j-2)x)\sin((i-j)*x))\\
=\sin x*\sin((i-1)*x)+2*\cos x*g[i-1]-g[i-2]\]

其中 \(\sin((i-1)*x)\) 虽然不是常数,但是也可以通过矩阵乘法得到。

更一般地,令 \(dp[i][j]\) 表示 j 个多项式卷积第 i 项的系数,我们可以得到如下的递推关系:

\[\begin{cases}dp[i][j]=\sin x*dp[i-1][j-1]+2*\cos x*dp[i-1][j]-dp[i-2][j] & i \geq 2 \\
dp[i][j] = \sin x & i = 1 且 j = 1\\
dp[i][j] = 0 & otherwise
\end{cases}\]

然后就可以矩阵加速了。

@accepted code@

不知道为什么,求解非零位时必须按照标程写才能过。

如果 p 一直作除法改成 ans 一直作乘法就过不了。

是因为后者浮点误差太大了吗?如果有知道的拜托请评论在下面告诉我好吗 QAQ。

#include<cstdio>
#include<cmath>
const int MAXN = 30;
struct matrix{
int r, c;
double m[MAXN*2 + 5][MAXN*2 + 5];
}M, B;
matrix operator * (matrix A, matrix B) {
matrix C; C.r = A.r, C.c = B.c;
for(int i=0;i<C.r;i++)
for(int j=0;j<C.c;j++) {
C.m[i][j] = 0;
for(int k=0;k<A.c;k++)
C.m[i][j] += A.m[i][k]*B.m[k][j];
}
return C;
}
/*
void Print(matrix M) {
puts("");
for(int i=0;i<M.r;i++) {
for(int j=0;j<M.c;j++)
printf("%lf ", M.m[i][j]);
puts("");
}
puts("");
}
*/
matrix qpow(matrix A, int p) {
matrix ret; ret.r = A.r, ret.c = A.c;
for(int i=0;i<ret.r;i++)
for(int j=0;j<ret.c;j++)
ret.m[i][j] = (i == j);
while( p ) {
if( p & 1 ) ret = ret * A;
A = A * A;
p >>= 1;
}
return ret;
}
void solve() {
int m, n; double x;
scanf("%d%d%lf", &m, &n, &x);
B.r = 2*m, B.c = 1, B.m[0][0] = 1;
for(int i=0;i<2*m;i++)
B.m[i][0] = 0;
B.m[m-1][0] = sin(x);
M.r = M.c = 2*m;
for(int i=0;i<2*m;i++)
for(int j=0;j<2*m;j++)
M.m[i][j] = 0;
for(int i=0;i<m;i++) {
M.m[i][i] = 2*cos(x);
M.m[i][m + i] = -1;
M.m[m + i][i] = 1;
}
for(int i=2;i<=m;i++)
M.m[i-2][i-1] = sin(x);
//Print(M); Print(B);
//Print(qpow(M, n-1)*B);
double ans = (qpow(M, n-1)*B).m[0][0];
putchar(ans > 0 ? '+' : '-');
ans = fabs(ans);
if( ans > 1 ) {
while( ans >= 10 ) ans /= 10;
printf("%d\n", int(ans));
}
else {
double p = 0.1;
while( p > ans ) p /= 10;
printf("%d\n", int(ans/p));
}
}
int main() {
int T; scanf("%d", &T);
for(int i=1;i<=T;i++) solve();
}

@details@

不得不说这道题还真的挺容易让人走错方向来着。

首先这是一个卷积形式,一开始肯定是思考能不能用 FFT(特别是像我一样最近才入多项式这个坑什么都想先来 FFT 一下)。

然后 m 个正整数的和为 n,又是一个组合数学的经典问题。这又是一个大坑。

然后 sin(x),一样是因为最近学了多项式,搞得我都想泰勒展开了……

当然如果你是神犇肯定不会像我一样去想上面那些错误思路而是一眼就秒出了这道题的正解。

@雅礼集训01/06 - T3@ math的更多相关文章

  1. @雅礼集训01/13 - T1@ union

    目录 @description@ @solution@ @part - 1@ @part - 2@ @part - 3@ @accepted code@ @details@ @description@ ...

  2. @雅礼集训01/10 - T1@ matrix

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个矩阵.求它的所有子矩阵中本质不同的行的个数之和. inp ...

  3. [LOJ 6030]「雅礼集训 2017 Day1」矩阵

    [LOJ 6030] 「雅礼集训 2017 Day1」矩阵 题意 给定一个 \(n\times n\) 的 01 矩阵, 每次操作可以将一行转置后赋值给某一列, 问最少几次操作能让矩阵全为 1. 无解 ...

  4. 雅礼集训1-9day爆零记

    雅礼集训1-9day爆零记 先膜一下虐爆我的JEFF巨佬 Day0 我也不知道我要去干嘛,就不想搞文化科 (文化太辣鸡了.jpg) 听李总说可以去看(羡慕)各路大佬谈笑风声,我就报一个名吧,没想到还真 ...

  5. LOJ_6045_「雅礼集训 2017 Day8」价 _最小割

    LOJ_6045_「雅礼集训 2017 Day8」价 _最小割 描述: 有$n$种减肥药,$n$种药材,每种减肥药有一些对应的药材和一个收益. 假设选择吃下$K$种减肥药,那么需要这$K$种减肥药包含 ...

  6. 雅礼集训【Day6-1】字符串

    雅礼集训[Day6-1]字符串 假设我们有串\(a\),我们设\(a'\)为\(a\)翻转后按为取反过后的串. 我们只考虑前一半的,长为\(m\)的串.如果前半截匹配了\(a\)或者\(a'\),则\ ...

  7. 「雅礼集训 2017 Day7」事情的相似度

    「雅礼集训 2017 Day7」事情的相似度 题目链接 我们先将字符串建后缀自动机.然后对于两个前缀\([1,i]\),\([1,j]\),他们的最长公共后缀长度就是他们在\(fail\)树上对应节点 ...

  8. 「雅礼集训 2017 Day2」解题报告

    「雅礼集训 2017 Day2」水箱 我怎么知道这种题目都能构造树形结构. 根据高度构造一棵树,在树上倍增找到最大的小于约束条件高度的隔板,开一个 \(vector\) 记录一下,然后对于每个 \(v ...

  9. 「雅礼集训 2017 Day1」 解题报告

    「雅礼集训 2017 Day1」市场 挺神仙的一题.涉及区间加.区间除.区间最小值和区间和.虽然标算就是暴力,但是复杂度是有保证的. 我们知道如果线段树上的一个结点,\(max=min\) 或者 \( ...

随机推荐

  1. Spring_Hibernate整合准备

    1,Spring整合Hibernate   整合什么? 1)由IOC容器来生成Hibernate的SessionFactory 2)让Hibernate使用上Spring的声明式事务 2,整合步骤 1 ...

  2. Codeforces Round #573 (Div. 2)

    A:Tokitsukaze and Enhancement 当时看错条件了..以为A>C>B>D.就胡写了判断条件. #include<bits/stdc++.h> us ...

  3. 直接在安装了redis的Linux机器上操作redis数据存储类型--List类型

    一.概述: 在Redis中,List类型是按照插入顺序排序的字符串链表.和数据结构中的普通链表一样,我们可以在其头部(left)和尾部(right)添加新的元素.在插入时,如果该键并不存在,Redis ...

  4. java.lang.IllegalStateException: 1 matchers expected, 5 recorded.

    这是一个很神奇的错误. 常规的出错是因为在mock方法里,其中某一个或者几个参数使用了EasyMock.anyxx(),而其他的使用了具体的值. java.lang.IllegalStateExcep ...

  5. JSP/FTL 中获取param、request、session、application中的值

      Java JSP(EL表达式) FTL ① <% page.getAttribute("attr") %> ${pageScope .attr} - ② reque ...

  6. MacBook下为要运行的.net core 项目指定sdk版本

    安装完.net core 3.0,运行早期版本构建的项目遇到运行错误,查阅官方文档解决问题,特此记录!官方原文如下: SDK 使用最新安装的版本 SDK 命令包括 dotnet new 和 dotne ...

  7. LintCode刷题笔记-- BackpackIV

    标签: 动态规划 描述: Given an integer array nums with all positive numbers and no duplicates, find the numbe ...

  8. Web编译器Visual Studio扩展

    原文地址:https://marketplace.visualstudio.com/items?itemName=MadsKristensen.WebCompiler 一个Visual Studio扩 ...

  9. 备考2019年6月份PMP考试-分享一些考试笔记(二)

    最新比较经典的100道试题,有备考的小伙伴可以练练手,文章末尾附答案. 1     一个项目经理在运作一个数据中心安装项目.他发现相关方很恼火,因为他超出了预算,原因是人员费用要高于原先的计划.另外项 ...

  10. Windows10 +Ubuntu 18.04双系统安装详细教程

    前言: 由于开发需要,很多用户需要安装Linux环境.如果用虚拟机操作会消耗大量内存,一般的电脑会显得卡顿,从而影响开发效率.这里分享一些安装经验,希望能够帮助大家. 教程: 步骤1:下载镜像文件 从 ...