某考试 T1 sigfib

设 g(x) = f(x) * x ,多项式 A = Σ g(i) * x^i , 多项式  B = Σ f(i) * x^i。

首先,g(x) = g(x-1) + g(x-2) + f(x-1) + 2f(x-2),所以我们可以得到: A = x * A + x^2 * A + x * B + 2 * x^2 * B + x

又因为B是斐波那契数列的多项式,所以B的闭形式可以直接得到,就是  x/(1-x-x^2)   [这个也不难推,可以自己推推]。

于是我们可以开开心心的解出A的闭形式,发现分母是 (1-x-x^2)^2.

然后我们再把 A^3 求出来就可以直接得到答案了, 这个时候分母就是 (1-x-x^2)^6 ,于是我们就可以直接得到一个 A^3 代表的函数的递推式(最好选择让计算机多项式乘法算递推式的系数,不然手算很可能会gg),每一项之和前面的12项有关。 [至于为什么不用考虑分子->因为分子的x的次数和系数只能决定生成函数整体的伸缩和平移,而和递推式没有任何联系,所以可以直接忽略]。

所以现在就可以直接矩阵快速幂了。

是吗?

发现极限数据可能会有 10^5 级别的数据组数,总的复杂度就是 O(10^5 * 12^3 * log(10^18)),然后就凉了。

不过发现M<=100的时候这个数列的循环节特别短,所以可以直接预处理出来然后 M<=100的时候O(1)回答询问。

emmmm,这就做完了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
int M,T,NUM[13]={0,6,-9,-10,30,6,-41,-6,30,10,-9,-6,-1};
int f[233],F[233],A[12],B[12];
int ans[105][100005],C[13],len[105];
inline int add(int x,int y,const int ha){
	x+=y;
	return x>=ha?x-ha:x;
}
struct node{
	int a[12][12];
	inline void clear(){ memset(a,0,sizeof(a));}
	inline void BASE(){ clear(); for(int i=0;i<12;i++) a[i][i]=1;}
	node operator *(const node &u)const{
		node r; r.clear();
		for(int k=0;k<12;k++)
		    for(int i=0;i<12;i++)
		        for(int j=0;j<12;j++) r.a[i][j]=add(r.a[i][j],a[i][k]*(ll)u.a[k][j]%M,M);
		return r;
	}
}ANS,X;
ll N,ci[66];

inline void init(){
	ci[0]=1;
	for(int i=1;i<=60;i++) ci[i]=ci[i-1]+ci[i-1];

	f[1]=f[2]=1;
	for(int i=3;i<=12;i++) f[i]=f[i-1]+f[i-2];
	for(int i=1;i<=12;i++)
	    for(int j=1;i+j<=12;j++)
	        for(int l=1;l+i+j<=12;l++) F[i+j+l]+=f[i]*f[j]*f[l]*i*j*l;

	for(M=2;M<=100;M++){
		for(int i=1;i<=12;i++) C[i]=add(NUM[i]%M,M,M),ans[M][i]=add(F[i]%M,M,M);
		for(int i=13;i;i++){
			for(int j=1;j<=12;j++) ans[M][i]=add(ans[M][i],C[j]*(ll)ans[M][i-j]%M,M);
			bool flag=1;
			for(int j=1;j<=12;j++) if(ans[M][j]!=ans[M][i+j-12]){
				flag=0;
				break;
			}

			if(flag){
				len[M]=i-12;
				break;
			}
		}
	}
}

inline void solve(){
	scanf("%d%lld",&M,&N);
	if(M==1) puts("0");
	else if(N<=12) printf("%d\n",add(F[N]%M,M,M)*6ll%M);
	else if(M<=100) printf("%d\n",ans[M][(N-1)%len[M]+1]*6ll%M);
	else{
		X.clear(),ANS.BASE(),N-=12;
		for(int i=0;i<11;i++) X.a[i][i+1]=1;
		for(int i=0;i<12;i++) X.a[i][0]=add(NUM[i+1]%M,M,M);
		for(;N;N>>=1,X=X*X) if(N&1) ANS=ANS*X;

		for(int i=0;i<12;i++) A[i]=add(F[12-i]%M,M,M);
		memset(B,0,sizeof(B));
		for(int j=0;j<12;j++)
		    for(int l=0;l<12;l++) B[l]=add(B[l],A[j]*(ll)ANS.a[j][l]%M,M);
		printf("%d\n",B[0]*6ll%M);
	}
}

int main(){
//	freopen("sigfib.in","r",stdin);
//	freopen("sigfib.out","w",stdout);
	init();
	scanf("%d",&T);
	while(T--) solve();
	return 0;
}

  

原文地址:https://www.cnblogs.com/JYYHH/p/8822572.html

时间: 2024-08-30 18:27:09

某考试 T1 sigfib的相关文章

某考试T1 game

题目背景 无 题目描述 Alice 和 Bob 在一个圆环上玩游戏.圆环上有 n 个位置,按照顺时针顺序 依次标号为 1 到 n.Alice 和 Bob 分别有一个数字集合,集合中都是在 [1, n?1] 内的正整数.游戏开始时会有一个棋子摆在圆环上的某个位置,然后两人轮流 行动.轮到某个人的回合时,他可以从他的集合中选出某个数 x,然后把棋子 沿顺时针方向移动 x 个位置.如果某个人把棋子移动到了 1 号位置,那么他就 获胜了.两个人都会以最优策略行动. 你需要对不同先后手顺序以及棋子初始位置

16.1112 模拟考试 T1

加密[问题描述]有一种不讲道理的加密方法是: 在字符串的任意位置随机插入字符. 相应的,不讲道理的解密方法就是从字符串中恰好删去随机插入的那些字符.给定原文s和加密后的字符串t,求?有多少子串可以通过解密得到原文s.[输入格式]输入第一行包含一个字符串t,第二行包含一个字符串s.[输出格式]输出一行,包含一个整数,代表可以通过解密得到原文的s的子串的数量.[样例输入]abcabcabccba[样例输出]9[样例解释]用[?,?]表示子串开头结尾的下标(从 0 开始编号) ,这 9 种方案是:[0

某考试 T1 Hello my friend

Discription 原文地址:https://www.cnblogs.com/JYYHH/p/8870108.html

某考试 T1 fair (18.5.1版)

转化一下模型:每天可以选1也可以选0,但是任意前i天(i<=n)1的个数都必须>=0的个数,求总方案数/2^n. 然后可以发现这是一个经典题,随便推一下公式发现等于  C(n,n/2)/2^n  [请在二维平面直角坐标系上自行演算,(x,y)可以到 (x+1,y)和(x,y+1),横坐标代表1的个数,纵坐标代表0的个数,求不经过 y=x+1 这条直线的路径总数  (重点是 任意 (x,y) 满足 x+y==n 且 x>=y)] 本来以为卡卡常数就过去了23333,没想到竟然还要用 阶乘逼

某考试 T1 lcm

把lcm写成 (a+n)*(b+n) / gcd(a+n,b+n). 因为gcd可以辗转相减,所以就成了gcd(abs(a-b),a+n),一个常量一个变量之间的gcd,我们可以直接把abs(a-b)的所有约数找出来,然后看a要有某个约数的话n至少是多少,更新答案即可.(因为1e9以下的数的最多的约数的级别是1e3) #include<iostream> #include<cstdio> #include<algorithm> #include<cmath>

2020.3.1考试T1 多项式

出题人很凉心的把算法写成了题目名 首先我们可以发现每一维的贡献是独立的,这可以从 \(solve1\) 里看出来 然后我们可以考虑转化为 \(DP\) ,这可以从 \(solve2\) 里看出来 我们统计每一维能产生的贡献,就是 \(a\) 个 \(0\) 面, \(b\) 个 \(1\) 面, \(c\) 个 \(2\) 面这种形式,能写成一个多项式 \(ax^0+bx^1+cx^2\),而我们最终显然就是把所有的多项式都乘起来. 暴力一个一个乘就很 naive,分治 \(NTT\) 解决就好

好多考试....

11.01 早上考试 T1 虎... 这题真是虎,大力才结论,水掉了... 每一次翻转一定是只翻转白色连续的一段,然后dfs一遍就行了 #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <iostream> #define ll long long #define mem(a,b) memset(a,b,sizeof(a))

BZOJ 1711: [Usaco2007 Open]Dining吃饭

1711: [Usaco2007 Open]Dining吃饭 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 902  Solved: 476[Submit][Status][Discuss] Description 农夫JOHN为牛们做了很好的食品,但是牛吃饭很挑食. 每一头牛只喜欢吃一些食品和饮料而别的一概不吃.虽然他不一定能把所有牛喂饱,他还是想让尽可能多的牛吃到他们喜欢的食品和饮料. 农夫JOHN做了F (1 <= F <= 100) 种食品

暑假集训D17总结

考试 玄学的一次考试= = T1乱搞 只会乱搞出前二十分  然后真的拿了二十分 T2模拟 自己造数据 没有一个是在十分钟内跳出来的 然后竟然A了 T3暴力 觉得如果老爷机心情不好就会被卡到20  然后竟然时限太大拿了40 全是玄学= = 看成绩先按了一下$End$,然后莫名翻回了顶部 内部题,就不写题解了 刷题 随便刷吧 话说1A竟然被怀疑,我要是不练1A能力我还考啥试= = 然后在邻接表数组大小上被坑了两次 心累啊 然后考试A掉的T2,竟然在HZOJ上T了WTF,原因是TL开小了,然后开大到4