#6264. friend-斐波那契 题解
题面:
显然,这道题不能用一般的矩阵快速幂做。
首先这道题有两种思路:
第一种是wljss在课上讲的图解法
第二种也是讲过的推导法
在得到这个最后的式子后,就该考虑构造一个怎样的矩阵。
显然,根据以上得出来的结论,我们可以构造这样一个矩阵:
$ \begin{bmatrix}
ans_{n-1} &f_{n} ^{2} & f_{n-1} ^{2} &f_{n}f_{n-1}\
& & & \
& & & \
& & &
\end{bmatrix}*\begin{bmatrix}
1& 0 & 0 & 0\
1& 1 & 1 & 1\
0& 1 & 0 &0 \
0& 2 & 0 &1
\end{bmatrix}=\begin{bmatrix}
ans_{n} &f_{n+1} ^{2} & f_{n}^{2} & f_{n+1}f_{n} \
& & & \
& & & \
& & &
\end{bmatrix} $
弄明白其中原理代码就很好写了(bushi)
图解法
#include<string.h>
#include<stdio.h>
#define ll long long
#define MOD 1000000007
struct nobe{ll a[2][2];nobe(){memset(a,0,sizeof(a));} };
ll n;
ll sum;
nobe mut(nobe x,nobe y){
nobe res;
for(ll i=0;i<2;i++)for( int j=0;j<2;j++)for( int k=0;k<2;k++)
res.a[i][j]=(res.a[i][j]+x.a[i][k]*y.a[k][j])%MOD;
return res;
}//2-2矩阵乘法
void quick(ll n){
nobe c,res;
c.a[0][0]=c.a[0][1]=c.a[1][0]=1;
c.a[1][1]=0;
for(int i=0;i<2;i++) res.a[i][i]=1;
while(n)
{
if(n&1)res=mut(res,c);
c=mut(c,c);
n=n>>1;
}//F(0)=0,F(1)=1,F(2)=1且res矩阵每个数都会变化,没有规律
printf("%lld\n",(res.a[0][0]%MOD)*(res.a[1][0]%MOD)%MOD);//这是对的
}
int main(){
while(scanf("%lld",&n)!=EOF)
quick(n);
return 0;
}
由于本蒟蒻实在不懂如何实现推导法的代码。
所以这里不会列出推导的代码
这里放上一份dalao的代码
#include <bits/stdc++.h>
using namespace std;
const int N = 2*1e6+1;
long long n, ans, tot;
long long p[N], pan[N], phi[N];
long long f[N];
long long GCD(int a, int b) {
return b ? GCD(b, a%b) : a;
}
void init() {
phi[1] = 1;
for (int i = 2; i <= n; i ++) {
if (pan[i] == 0) {
p[++tot] = i;
phi[i] = i - 1;
}
for (int j = 1; j <= tot && i * p[j] <= n; j ++) {
pan[i*p[j]] = 1;
if (i % p[j] == 0) {
phi[i*p[j]] = phi[i] * p[j];
break;
}
phi[i*p[j]] = phi[i] * (p[j] - 1);
}
}
}
int main() {
while(cin >> n) {
if (n == 0) return 0;
init();
for (int i = 1; i <= n; i ++) {
for (int j = i * 2; j <= n; j += i) {
f[j]+=i*phi[j/i];
}
}
for(int i = 1; i <= n; i++) f[i] += f[i-1];
printf("%lld\n", f[n]);
}
return 0;
}
特别鸣谢:@XuYu0317 为本文提供关于LaTeX的技术支持(指一点点微乎其微的帮助),感谢他的贡献。
本文来自博客园,作者:deviancez,转载请注明原文链接:https://www.cnblogs.com/deviance/articles/18112968