2019 牛客第五场 B

题目地址

        当时以一看见这题,n的范围这么大,脑子里全是欧拉降幂。(感觉要是有人跟我说这不是欧拉降幂,我就跟他急似的);然后就瞎搞了很久,然后。。。。。就没有然后了。比赛结束后看了一下题解

出这题是因为我小时候曾被Codeforces 某个不是用2 进制倍增,而是改用10 进制倍增就会
很好写的题震慑到,所以这次找了个纯用2 进制倍增有点困难的题和大家分享

这是大佬题解的结束语,我哭了,小时候,和我小时玩的cf完全不是一个东西嘛;

思路:

        仿造我们写快速幂的写法,写快速幂的时候我们把指数按二进制分解了。其实只是方便而已。其实只有你高兴,随便你按几进制分解都可以。那么本题就是按照十进制分解的;哎,涨知识了
假设A是我们构造的矩阵,那么我们要求的就是A^n,(n是很大的数),最后的结果记为ans,ans初始为单位矩阵。那么让我们先处理出A的1次方~到A的九次方。比如我们n=12345465(字符表示的),那么我们从左到右处理,先是1,那么就是ans的10次方*A[1],之后是2,那么就是ans的10次方 * A[2],为什么这里是乘A,而不是加呢。记住n是这指数上,分开后就是乘法了。

#include<bits/stdc++.h>
using namespace std;

#define ll long long 
const int maxn = 1000 * 1000 + 10;

ll n, m, mod;
ll x0, x1, a, b;
char s[maxn];

inline ll ksc(ll x, ll y, ll p) {
	ll z = (long double)x / p * y;
	ll res = (unsigned ll)x*y - (unsigned ll)z*p;
	return (res + p) % p;
}

struct Mat {
	ll a[3][3];
	Mat() {
		memset(a, 0, sizeof(a));
	}
	Mat operator*(Mat A) {
		Mat ans;
		for (int i = 1; i <= 2; i++) {
			for (int j = 1; j <= 2; j++) {
				for (int k = 1; k <= 2; k++) {
					ans.a[i][j] = (ans.a[i][j] + a[i][k] * A.a[k][j]) % mod;
				}
			}
		}
		return ans;
	}

	Mat operator^(int n) {
		Mat ans;  ans.a[1][1] = ans.a[2][2] = 1;
		Mat a = *this;
		while (n) {
			if (n & 1)ans = ans * a;
			n >>= 1;
			a = a * a;
		}
		return ans;
	}

}Ma, Mb, M[10], ans;


void init() {
	M[0].a[1][1] = M[0].a[2][2] = 1;
	for (int i = 1; i < 10; i++)M[i] = M[i - 1] * Ma;
}

int main() {
	scanf("%lld%lld%lld%lld", &x0, &x1, &a, &b);
	scanf("%s", s);
	scanf("%lld", &mod);
	Ma.a[1][1] = a, Ma.a[1][2] = 1; Ma.a[2][1] = b, Ma.a[2][2] = 0;
	 Mb.a[1][1] = x1, Mb.a[1][2] = x0;
	 ans.a[1][1] = ans.a[2][2] = 1;

	init();
	ll n = 0, len = strlen(s);

	if (n == 1) {
		printf("%lld\n", x0);
		return 0;
	}

	for (ll i = 0; i < len; i++) {
		ans = ans^10;
		ans = ans * M[s[i] - '0'];
	}

	printf("%lld\n", (Mb*ans).a[1][2]);

	return 0;

}
发布了70 篇原创文章 · 获赞 5 · 访问量 7183

猜你喜欢

转载自blog.csdn.net/xiaonanxinyi/article/details/98105199
今日推荐