洛谷 5110 块速递推

水经验(逃
这个东西为什么能有紫啊……
推个递推式也没紫吧,这个烂大街的 trick 也没紫吧(

无脑上生成函数啊(
F(x)a 的生成函数,则 F(x)=233xF(x)+666x2F(x)+x(1233x666x2)F(x)=xF(x)=x1233x666x2

然后下一步就是得把这玩意部分分式展开。
大力待定系数设 1233x666x2=(1ax)(1bx)=1(a+b)x+abx(逃
则有 {a+b=233ab=666
解得 {a=233+133372b=233133372

然后继续大力待定系数设 x1233x666x2=A1ax+B1bx
解得 {A=113337B=113337
F(x)=113337(11ax11bx)
又有 an=113337[(233+133372)n(233133372)n]

关于那个根号,似乎可以扩域做,不过 337 是有二次剩余的。
跑个二次剩余算法得到 21628416827837158392337(mod(109+7))
随便拿一个来算就是了。

然后看起来要 O(1) 询问。
问题相当于支持 O(1) 询问 aba 是常数,0b<109+7
可以设一个块大小 W,预处理出 1,a,a2,a3,,aW11,aW,a2W,a3W,,aW(W1)
则可支持 O(1) 查询 0b<W2ab
然后如果把 W 设成 2 的次幂的话可以减少除法和取模的常数(用位运算代替)。
学出题人取了 W=216=65536

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <cstdio>
using namespace std;
namespace Mker
{
unsigned long long SA,SB,SC;
void init(){scanf("%llu%llu%llu",&SA,&SB,&SC);}
unsigned long long rand()
{
SA^=SA<<32,SA^=SA>>13,SA^=SA<<1;
unsigned long long t=SA;
SA=SB,SB=SC,SC^=t^SA;return SC;
}
}
const int mod = 1e9 + 7;
const int w[] = {233230706,94153035,64353223,905847205,847809841};
const int W = 65536;
int T,n;
int pw[5][W],ans;
int main()
{
pw[1][0] = pw[2][0] = pw[3][0] = pw[4][0] = 1;
for(register int i = 1;i <= 4;++i)
for(register int j = 1;j < W;++j)
pw[i][j] = (long long)pw[i][j - 1] * w[i] % mod;
scanf("%d",&T),Mker::init();
for(;T;--T)
n = Mker::rand() % (mod - 1),ans ^= w[0] * ((long long)pw[1][n & (W - 1)] * pw[2][n >> 16] % mod - (long long)pw[3][n & (W - 1)] * pw[4][n >> 16] % mod + mod) % mod;
printf("%d\n",ans);
}

0 comments
Anonymous
Markdown is supported

Be the first person to leave a comment!