2019-ACM-ICPC-南昌区网络赛-H. The Nth Item-特征根法求通项公式+二次剩余+欧拉降幂


【Problem Description】

​ 已知\(f(n)=3\cdot f(n-1)+2\cdot f(n-2),(n\ge 2)\),求\(f(n)\pmod {998244353}\)。

【Solution】

​ 利用特征根法求得通项公式为\(a_n=\frac{\sqrt{17}}{17}\cdot\Bigg(\Big(\frac{3+\sqrt{17}}{2} \Big)^n-\Big(\frac{3-\sqrt{17}}{2} \Big)^n\Bigg)\)。\(\sqrt{17}\pmod {998244353}\)可以用二次剩余求得。然后就可以用快速幂在\(O(log(n))\)的时间复杂度内求得\(a_n\)。但是因为\(T\le 10^7\),所以还需优化。

​ \(n\le 10^{18}\),进行欧拉降幂后\(n\le 10^9\),令\(k=\lfloor \sqrt{n}\rfloor\),则:

\[n=k\cdot t+r\\
x^n=x^{k\cdot t+r}\Leftrightarrow x^n=x^{k\cdot t}+x^r(t,r\le k)
\]

然后预处理出\(x^r,r\le k\)以及\(x^{k\cdot t},t\le k\)。则\(x^n\)就可以\(O(1)\)查询了。


【Code】

/*
* @Author: Simon
* @Date: 2019-09-08 13:13:29
* @Last Modified by: Simon
* @Last Modified time: 2019-09-17 17:44:39
*/
#include<bits/stdc++.h>
using namespace std;
typedef int Int;
#define int long long
#define INF 0x3f3f3f3f
#define maxn 100005
const int mod=998244353;
int inv17;
/*
* Author: Simon
* 功能: 求解x^2=n(mod p),即x=sqrt(n)(mod p)
* 复杂度: O(sqrt(p))
*/ /*类似复数 单位元为w(复数的单位元为-1)*/
struct Complex {
int x, y, w;
Complex() {}
Complex(int x, int y, int w) : x(x), y(y), w(w) {}
};
/*类复数乘法 */
Complex mul(Complex a, Complex b, int p) {
Complex ans;
ans.x = (a.x * b.x % p + a.y * b.y % p * a.w % p) % p;
ans.y = (a.x * b.y % p + a.y * b.x % p) % p;
ans.w = a.w;
return ans;
}
/*类复数快速幂 */
Complex Complexfpow(Complex a, int b, int mod) {
Complex ans = Complex(1, 0, a.w);
while (b) {
if (b & 1) ans = mul(ans, a, mod);
a = mul(a, a, mod);
b >>= 1;
}
return ans;
}
int fpow(int a, int b, int mod) {
int ans = 1;
a %= mod;
while (b) {
if (b & 1) (ans *= a) %= mod;
(a *= a) %= mod;
b >>= 1;
}
return ans;
}
/*求解x^2=n(mod p) */
int solve(int n, int p) {
n %= p;
if (n == 0) return 0;
if (p == 2) return n;
if (fpow(n, (p - 1) / 2, p) == p - 1) return -1; /*勒让德定理判断n不是p的二次剩余 */
mt19937 rnd(time(0));
int a, t, w;
do {
a = rnd() % p;
t = a * a - n;
w = (t % p + p) % p; /*构造w=a^2-n */
} while (fpow(w, (p - 1) / 2, p) != p - 1); /*找到一个w不是p的二次剩余 */
Complex ans = Complex(a, 1, w);
ans = Complexfpow(ans, (p + 1) / 2, p); /*答案为(a+w)^{(p+1)/2} */
return ans.x;
}
pair<int,int> bit1[maxn],bit2[maxn];
Int main(){
#ifndef ONLINE_JUDGE
//freopen("input.in","r",stdin);
//freopen("output.out","w",stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);inv17=fpow(17,mod-2,mod);
int x=solve(17,mod); //二次剩余
int lim=ceil(sqrt(1e9));
int s1=(3+x)%mod*fpow(2,mod-2,mod)%mod,
s2=(3-x)%mod*fpow(2,mod-2,mod)%mod;
bit1[0].first=bit1[0].second=bit2[0].first=bit2[0].second=1;
for(int i=1;i<=lim;i++){ //预处理
bit1[i].first=bit1[i-1].first*s1%mod;
bit1[i].second=bit1[i-1].second*s2%mod;
bit2[i].first=fpow(s1,i*lim,mod);
bit2[i].second=fpow(s2,i*lim,mod);
}
int q,n;cin>>q>>n;
int ans=0;
while(q--){
int tmp=0;
if(n==0) tmp=0;
else if(n==1) tmp=1;
else{
int t=n%(mod-1);
int t2=t/lim,t1=t%lim;
tmp=(bit1[t1].first*bit2[t2].first%mod-bit1[t1].second*bit2[t2].second%mod)%mod*x%mod*inv17%mod;
}
tmp=(tmp+mod)%mod;
n=tmp*tmp^n; ans^=tmp;
// cout<<n<<endl;
}
cout<<(ans+mod)%mod<<endl;
#ifndef ONLINE_JUDGE
cout<<endl;system("pause");
#endif
return 0;
}

最新文章

  1. android shape的使用(转)
  2. VC++ 应用程序无法正常启动0xc0150002
  3. 各种文件的mime类型
  4. getElementByName()和getElementById的区别
  5. Mysql-windows下修改密码
  6. UIScrollView控件实现图片缩放功能
  7. 数据库知识整理&lt;二&gt;
  8. java中无符号类型的处理
  9. HDU5791--Two (DP)
  10. c++11 线程:让你的多线程任务更轻松
  11. Spring中引入其他配置文件
  12. P1273 有线电视网
  13. javaEE完整体系结构
  14. 来自师兄的Django2.0笔记摘录
  15. Guava 1:概览
  16. Flume调优
  17. C/C++ 中嵌入 arm 汇编
  18. Android 自定义View二(深入了解自定义属性attrs.xml)
  19. [原]openstack-kilo--issue(十三)Unauthorized: The request you have made requires authentication. (HTTP 401) (Request
  20. mysql 问题:wait_timeout

热门文章

  1. 触屏Tap模拟事件
  2. java四大名著及idea常用插件
  3. LeetCode 590. N叉树的后序遍历(N-ary Tree Postorder Traversal)
  4. tomcat+java+redis环境linux安装
  5. (8)Spring Boot 与数据访问
  6. [C++] 例题 2.7.1 用栈实现简易计算器
  7. 【MIT 6.824 】分布式系统 课程笔记(一)
  8. 图像处理库 Pillow与PIL
  9. Qt4 和 Qt5 模块的分类
  10. mongodb入门基本语法