数学基础知识入门

Raising Modulo Numbers POJ - 1995

题目描述
计算 ( A 1 B 1 + A 2 B 2 + . . . + A H B H ) m o d M (A1^{B1}+A2^{B2}+ ... +AH^{BH})mod M (A1B1+A2B2+...+AHBH)modM.

输入格式
输入数据的第一行是一个数字 Z,它表明该测试数据的组数。
然后是 Z 组测试数据,每组测试用例第一行是模数 M (1 ≤ M ≤ 45000),即代表对 M 取模,第二行是项数 H,代表有 H (1 ≤ H ≤ 45000) 项,接下来正好是 H 行,在每一行上,有两个数字 Ai 和 Bi,并且两者由空格分隔。两个数字不能同时为零。

输出格式
对于每个样例输出一行,代表答案

输入样例

3
16
4
2 3
3 4
4 5
5 6
36123
1
2374859 3029382
17
1
3 18132

输出样例

2
13195
13
  • 参考程序
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N=1e5+10, INF=(1<<30);
typedef long long ll;
ll a[N], b[N];
ll pow(ll a,ll n,ll m){
    ll ans=1, mod=m;
    while(n){
        if(n&1) ans=ans*a%mod;
        a = a*a%mod;
        n >>= 1;
    }
    return  ans;
}
int main(){
//    freopen("data.in", "r", stdin);
    int z; cin>>z;
    while(z--){
        ll m,h,ans=0;cin>>m>>h;
        for(int i=1; i<=h; i++) cin>>a[i]>>b[i];
        for(int i=1; i<=h; i++){
            ans = (ans+pow(a[i], b[i], m)) % m;
        }
        cout<<ans<<endl;
    }
    return 0;
}

Pseudoprime numbers POJ - 3641

题目描述
费马定理指出,对于任意的素数 p 和任意的整数 a > 1,满足 ap = a (mod p) 。
然而,并不一定满足这个条件的都是素数。
我们称p是基于a的伪素数当且仅当p不是素数,但是满足a^p=a(mod p)。

给定 2 < p ≤ 1000000000 且 1 < a < p ,判断 p 是否为以 a 为底的伪素数。

输入格式
输入包含多个测试用例,以 “0 0” 表示输入结束。
每个测试用例,由包含 p 和 a 的一行组成。

输出格式
对于每个测试用例,如果 p 是以 a 为底的伪素数,则输出 “yes”,否则输出 “no” 。

输入样例

3 2
10 3
341 2
341 3
1105 2
1105 3
0 0

输出样例

no
no
yes
no
yes
yes
  • 参考程序
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int N=1e6+10, INF=(1<<30);
bool isprime(int n){
    if(n<2) return 0;
    for(int i=2; i*i<=n; i++) if(n%i==0) return 0;
    return 1;
}
ll pow(ll a,ll n,ll m){
    ll ans=1, mod=m;
    while(n){
        if(n&1) ans=ans*a%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans;
}
int main(){
//    freopen("data.in", "r", stdin);
    int p,a;
    while(cin>>p>>a){
        if(p==0 && a==0) break;
        if(pow(a,p,p)==a%p && !isprime(p)){
            cout<<"yes"<<endl;
        }else cout<<"no"<<endl;
    }
    return 0;
}

分数加减法 POJ - 3979

题目描述
编写一个C程序,实现两个分数的加减法

输入格式
输入包含多行数据,每行数据是一个字符串,格式是"a/boc/d"。
其中a, b, c, d是一个0-9的整数。o是运算符"+“或者”-"。
数据以EOF结束,输入数据保证合法

输出格式
对于输入数据的每一行输出两个分数的运算结果。
注意结果应符合书写习惯,没有多余的符号、分子、分母,并且化简至最简分数

输入样例

1/8+3/8
1/4-1/2
1/3-1/3

输出样例

1/2
-1/4
0
  • 参考程序
#include<iostream>
#include<cstdio>
using namespace std;
const int N=1e4+10, inf=0x3f3f3f3f;
int gcd(int a,int b){
    return  b==0 ? a : gcd(b, a%b);
}
int main() {
//    freopen("data.in", "r", stdin);
    char s[20],o;
    while(scanf("%s", s)!=EOF){
        int a,b,c,d,f=1,ans1,ans2,temp;
        sscanf(s, "%1d/%1d%c%1d/%1d",&a,&b,&o,&c,&d);
        if(o=='+') ans1 = a*d + b*c, ans2=b*d;
        else if(o=='-') ans1 = a*d - b*c, ans2=b*d;

        if(ans1<0) f=-1, ans1=-ans1;
        temp = gcd(ans1, ans2);
        ans1 = f*ans1/temp;
        ans2 = ans2/temp;
        
        if(ans1==0) puts("0");
        else if(ans2==1) printf("%d\n", ans1); 
        else printf("%d/%d\n",ans1,ans2);
    }
    return 0;
}

Goldbach’s Conjecture POJ - 2262

题目描述
1742年,德国业余数学家克里斯蒂安·哥德巴赫给莱昂哈德·欧拉发了一封信,信中他做出了如下猜想: 每一个大于4的偶数都可以是 写成两个奇数素数之和。
For example:
8 = 3 + 5. Both 3 and 5 are odd prime numbers.
20 = 3 + 17 = 7 + 13.
42 = 5 + 37 = 11 + 31 = 13 + 29 = 19 + 23.
今天,这个猜想是否正确还没有得到证实。(哦,等等,我当然有证据,但太长了,不能写在这页的空白处。) 不管怎样,你现在的任务是验证哥德巴赫猜想对于所有小于一百万的偶数。

输入格式
输入将包含一个或多个测试用例。
每个测试用例由一个偶数整数n组成,其中6 <= n < 1000000。
对于n,输入将以值0终止。

输出格式
对于每个测试用例,打印一行形式n = a + b,其中a和b是奇数素数。
数字和运算符应该像下面的样例输出一样,用一个空白隔开。
如果有一对以上的奇素数加起来为n,选择差b-a最大的对。
如果没有这样的对,打印一行写着“Goldbach’s conjecture is wrong.”

输入样例

8
20
42
0

输出样例

8 = 3 + 5
20 = 3 + 17
42 = 5 + 37
  • 参考程序
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int N=1e6+10, INF=(1<<30);
bool isprime(int n){
    if(n<2) return 0;
    for(int i=2; i*i<=n; i++) if(n%i==0) return 0;
    return 1;
}
int main(){
//    freopen("data.in", "r", stdin);
    int n;
    while(cin>>n){
        if(n==0) break;
        bool flag=0;
        for(int i=2; i<=n; i++){
            if(isprime(i) && isprime(n-i)){
                printf("%d = %d + %d\n",n,i,n-i);
                flag=1; break;
            }
        }
        if(flag==0) puts("Goldbach's conjecture is wrong.");
    }
    return 0;
}

Prime Distance POJ - 2689

题目描述
给定 L,R,求区间 [L,R]中距离最近的一对素数 p1<p2,和距离最远的一对素数 p3<p4。
如果不止一对素数距离最近(远),输出第一对。

输入格式
多组数据,每组一行两个整数 L,R;1≤L<R≤2,147,483,647,R−L≤1,000,000

输出格式
每组一行,有解输出两对素数,无解则输出无解信息

输入样例

2 17
14 17

输出样例

2,3 are closest, 7,11 are most distant.
There are no adjacent primes.
  • 分析:数据范围 2,147,483,647 较大,但是 R−L≤1,000,000。
  • 参考程序

Farey Sequence POJ - 2478

题目描述
众所周知,小涛涛学长是数论的king,artist今天去请教了他一个问题,小涛涛学长读完题目后,觉得太简单了,对artist十分失望,随即离开,只留下一个背影,artist向你求助,你能帮帮她吗? 有一个数列叫做dxl数列,对任意n,DXLn代表一个包含不可简化(不可约分)的有理分数a/b的序列,满足0 < a < b <= n且gcd(a,b)=1,序列中的分数按照递增顺序排列。 前几个DXLn为:
DXL2 = {1/2}
DXL3 = {1/3, 1/2, 2/3}
DXL4 = {1/4, 1/3, 1/2, 2/3, 3/4}
DXL5 = {1/5, 1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4, 4/5}
给定n,你的任务是计算序列DXLn的大小(即含有多少个分数)。
注意:这道题不支持头文件bits/stdc++.h!

题目简述:给定n(2<=n<=10^9),求出所有最简分数a/b的个数,满足条件:0<a<b<=n。

输入格式
多组数据,每行一个 n(2<=n<=1e6),读到0结束。

输出格式
每行输出一组数据的答案。

输入样例

2
3
4
5
0

输出样例

1
3
5
9

Semi-prime H-numbers POJ - 3292

题目描述
这个问题是基于David Hilbert的研究,David Hilbert研究4n + 1数的理论。

H数是一个正整数,它是比4的倍数大1:1,5,9,13,17,21 …是H数。
对于这个问题,我们假装这些都是唯一的数字。 H数在乘法下关闭。
与常规整数一样,我们将H数分为成两种,H-primes和H-composite。
H质数和H复合数,H质数指的是这个数除了1外 只有1个H数。除H质数外的都是H复合数。
例如,前几个H-复合数是:5×5 = 25,5×9 = 45,5×13 = 65,9×9 = 81,5×17 = 85。

你的任务是计算H-half-primes的数量。
H-半素数是H数,它恰好是两个H素数的乘积,两个H-素数可以相同或不同。
在上面的例子中,所有五个数字都是H-half-primes。
125 = 5×5×5不是H半素数,因为它是三个H素数的乘积。

输入格式
每行输入包含一个H值≤1,000,001。 最后一行输入包含0,程序运行结束。

输出格式
对于每个输入的H数h,打印一行表示h的行和在1和H之间的H-semi-primes的数量,以样本中所示的格式分隔一个空格。

输入样例

21 
85
789
0

输出样例

21 0
85 5
789 62

质因数分解 洛谷 - P1075

题目描述

已知正整数 n是两个不同的质数的乘积,试求出两者中较大的那个质数。

输入格式:一个正整数 n(n≤2×1e9 )。
输出格式:一个正整数 p,即较大的那个质数。
输入样例:21
输出样例:7

  • 参考程序
#include<iostream>
using namespace std;
bool isPrime(int n){//判断n是不是素数
    if(n<2) return false;
    for(int i=2; i*i<=n; i++) if(n%i==0) return false;
    return true;
}
int main_60(){
    int n;cin>>n;
    for(int i=n-1; i>=2; i--){
        if(isPrime(i) && isPrime(n/i) && n%i==0){
            cout<<i; break;//return 0;
        }
    }
    return 0;
}
int main_100() {
    int n;    cin>>n;
// 唯一分解定理:一个数能且只能分解为一组质数的乘积 N=p1*p2*...pm
// 也就是说如果输入数据满足要求,则 N 只能分解成两个质数的乘积。
    for(int i=2; i<=n; i++) {
        if(n%i==0) {    //最小的质因数
            cout<<n/i;  //输出最大的质因数
            break;
        }
    } return 0;
}

特殊的质数肋骨 Superprime Rib 洛谷 - P1218

题目描述
农民约翰的母牛总是产生最好的肋骨。
你能通过农民约翰和美国农业部标记在每根肋骨上的数字认出它们。

农民约翰确定他卖给买方的是真正的质数肋骨,是因为从右边开始切下肋骨,每次还剩下的肋骨上的数字都组成一个质数。举例来说:7 3 3 1 全部肋骨上的数字 7331 是质数;三根肋骨 733 是质数;二根肋骨 73 是质数;当然,最后一根肋骨 7 也是质数。7331 被叫做长度 4 的特殊质数。

写一个程序对给定的肋骨的数目 n,求出所有的特殊质数。1 不是质数。

输入格式:一行一个正整数 n。
输出格式:按顺序输出长度为 n 的特殊质数,每行一个。
输入样例:4
输出样例

2333
2339
2393
2399
2939
3119
3137
3733
3739
3793
3797
5939
7193
7331
7333
7393

数据范围:对于 100% 的数据,1≤n≤8。

  • 参考程序
#include<bits/stdc++.h>
using namespace std;
const int N=1e8+1;
bool isprime[N];
int primes[N], pn=0,a[N];
bool isPrime(int num){
    if(num<2) return 0;
    for(int i=2; i*i<=num; i++) if(num%i==0) return 0;
    return 1;
}
//埃式筛法 - 埃拉托斯特尼筛法
//筛除倍数,一个素数的倍数一定不是素数
void Eratosthenes(int maxn){
// 初始化isprime全部为1,即初始化所有i为质数
    memset(isprime, 1, sizeof(isprime));
    isprime[0] = isprime[1] = pn = 0;//0,1不是质数
    for(int i=2; i<=maxn; i++){
        if(isprime[i]==0) continue;  //退出当前循环,继续下次循环
        primes[++pn] = i;            //将质数 i存入primes
        for(int j=2; i*j<=maxn; j++){
            isprime[i*j] = 0;        //质数的倍数都是合数
        }
    }
}
//线性筛法 - 欧拉筛法
void FastSieve(int maxn){
// 初始化isprime全部为1,即初始化所有i为质数
    memset(isprime, 1, sizeof(isprime));//0,1不是质数
    isprime[0] = isprime[1] = pn = 0;
    for(int i=2; i<=maxn; i++){
        if(isprime[i]) primes[++pn] = i;//将质数 i存入primes
        for(int j=1; j<=pn; j++){
            if(i*primes[j] > maxn) break;
            isprime[i*primes[j]] = 0;   //质数的倍数都是合数
            if(i%primes[j]==0) break;   //利用最小素因子筛素数关键
        }
    }
}
int main(){
//    freopen("test.out", "w", stdout);
    int n=4; cin>>n;
    if(n == 8) {//这一点确实有点难,只能使用打表或者二分思想来解决
        cout<<"23399339"<<endl
          <<"29399999"<<endl
          <<"37337999"<<endl
          <<"59393339"<<endl
          <<"73939133"<<endl;return 0;
    }
    n = pow(10,n);

//    Eratosthenes(n);//埃氏筛法
    FastSieve(n);//线性筛法
    for(int i=n/10; i<=n-1; i++){
        int temp=i;
        while(temp){
            if(isprime[temp]==0) break;
            temp /= 10;
        }
        if(temp==0) cout<<i<<endl;
    }

/*  for(int i=1; i<=n; i++){
        if(primes[i] > n-1) break;
        if(n/10 <= primes[i]){
            int temp = primes[i];
            while(temp){
                if(isprimes[temp]==0) break;
                temp /= 10;
            }
            if(temp==0) cout<<primes[i]<<endl;
        }
    }*/
    return 0;
}

上面这个是用筛法程序做的,那么我们还是讲一讲取巧方法 - 打表
所谓打表,就是写一个最简单的程序,通过该程序得到部分中间数据,甚至是最终答案,从而达到能简化运算次数的目的。

#include<iostream>
#include<cmath>
using namespace std;
bool isPrime(int n){
    if(n<2) return 0;
    for(int i=2; i*i<=n; i++) if(n%i==0) return 0;
    return 1;
}
void pd() {//按要求打表 - 用朴素算法
    int n; cin>>n;
    n=pow(10,n);
    for(int i=2; i<=n; i++){
        if(isPrime(i)){
            int temp=i;
            while(temp){
                if(isPrime(temp)==0) break;
                temp /= 10;
            }
            if(temp==0) cout<<i<<",";
        }
    }
}

const int N=10;
int primes[N][20]={//按要求对素数(1~8位)打表
{},
{2,3,5,7},
{23,29,31,37,53,59,71,73,79},
{233,239,293,311,313,317,373,379,593,599,719,733,739,797},
{2333,2339,2393,2399,2939,3119,3137,3733,3739,3793,3797,5939,7193,7331,7333,7393},
{23333,23339,23399,23993,29399,31193,31379,37337,37339,37397,59393,59399,71933,73331,73939},
{233993,239933,293999,373379,373393,593933,593993,719333,739391,739393,739397,739399},
{2339933,2399333,2939999,3733799,5939333,7393913,7393931,7393933},
{23399339,29399999,37337999,59393339,73939133}};

int main() {
    int n; cin>>n;
    for(int i=0; primes[n][i]!=0; i++){
        cout<<primes[n][i]<<endl;
    }return 0;
}//相对线性筛法而言,这道题我更推荐使用打表的方法来解决,不过也就10几分钟的事情

image

Matrix Power Series POJ - 3233

题目描述

给一个 n × n 的矩阵 A 和两个整数 k, m。现有 S = A + A^2 + A^3 + … + A^k。

输出 S % m 后的结果(矩阵模上一个数等价于矩阵中每个元素模上这个数)

输入格式
输入的第一行为三个整数 n (n ≤ 30), k (k ≤ 109) and m (m < 104).
接下来 n行 每行包含 n 个 小于32768的非负整数,表示矩阵A。

输出格式:输出S模m后的矩阵

输入样例

2 2 4
0 1
1 1

输出样例

1 2
2 3
  • 分析:矩阵快速幂,但是会超时, 需要二分优化

定 义 : f ( k ) = A + A 2 + A 3 + … + A k ; 当 k 为 奇 数 时 : f ( k ) = f ( k − 1 ) + A k ; 当 k 为 偶 数 时 : f ( k ) = A + A 2 + A 3 + … + A k = A + A 2 + . . . + A k / 2 + ( A + A 2 + . . . + A k / 2 ) A k / 2 = f ( k / 2 ) + f ( k / 2 ) ∗ A k / 2 \begin{aligned} 定义:f(k) &= A + A^2 + A^3 + … + A^k; \\ \quad \\ 当 k 为奇数时: f(k) &= f(k-1) + A^k; \\ \quad \\ 当 k 为偶数时: f(k) &= A + A^2 + A^3 + … + A^k \\ \quad \\ &= A +A^2 +...+ A^{k/2} + (A +A^2 +...+ A^{k/2})A^{k/2} \\ \quad \\ &= f(k/2) +f(k/2)*A^{k/2} \end{aligned} f(k)k:f(k)k:f(k)=A+A2+A3++Ak;=f(k1)+Ak;=A+A2+A3++Ak=A+A2+...+Ak/2+(A+A2+...+Ak/2)Ak/2=f(k/2)+f(k/2)Ak/2

  • 参考程序
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
//#define int long long
const int N=31;
int mod=1e9+7, n,k,m;
struct Matrix {
	int l,r,data[N][N];
	Matrix(int a,int b):l(a), r(b) {
		memset(data, 0, sizeof(data));
	}
	Matrix operator+ (const Matrix& t) const {
		Matrix c(l, r);
		for(int i=1; i<=l; i++)
			for(int j=1; j<=r; j++)
				c.data[i][j] = (data[i][j]+t.data[i][j])%mod;
		return c;
	}
	Matrix operator- (const Matrix& t) const {
		Matrix c(l, r);
		for(int i=1; i<=l; i++)
			for(int j=1; j<=r; j++)
				c.data[i][j] = (data[i][j]-t.data[i][j])%mod;
		return c;
	}
	Matrix operator* (int k) const {
		Matrix c(l, r);
		for(int i=1; i<=l; i++)
			for(int j=1; j<=r; j++)
				c.data[i][j] = (k*data[i][j])%mod;
		return c;
	}
	Matrix operator* (const Matrix& t) const {
		Matrix c(l, t.r);
		for(int  k=1; k<=t.l; k++)
			for(int i=1; i<=c.l; i++)
				for(int j=1; j<=c.r; j++)
		c.data[i][j] = (c.data[i][j]+data[i][k]*t.data[k][j]%mod)%mod;
		return c;
	}
	void print() {
		for(int i=1; i<=l; i++) {
			for(int j=1; j<=r; j++) cout<<data[i][j]<<" ";
			cout<<endl;
		}
		cout<<endl;
	}
};
Matrix fastpow(Matrix a, int k) {
	Matrix ans(a.l, a.r);
	for(int i=1; i<=a.l; i++) ans.data[i][i]=1;
	while(k) {
		if(k&1) ans=ans*a;
		a = a*a;
		k>>=1;
	}
	return ans;
}
Matrix slove(Matrix a, int n){
    Matrix ans=a;
    if(n==1) return a;
    if(n&1) return slove(a, n-1) + fastpow(a, n);
    else {
        ans = slove(a, n>>1);
        return ans + ans*fastpow(a, n>>1);
    }
}
int main() {
//	freopen("data.in", "r", stdin);
    ios::sync_with_stdio(0);
	while(cin>>n>>k>>m) {
	    mod = m;
        Matrix base(n, n), a(n, n);
        for(int i=1; i<=n; i++) base.data[i][i]=1;
	    for(int i=1; i<=n; i++)
	        for(int j=1; j<=n; j++)  cin>>a.data[i][j];
            Matrix ans(a.l, a.r);
//            for(int i=1; i<=k; i++) ans = ans+fastpow(a, i); // TLE
//            for(int i=1; i<=k; i++) ans = (ans+base)*a;
            ans = slove(a, k);
            ans.print();
	}
	return 0;
}

Fibonacci POJ - 3070

题目描述

斐波那契数列中,F[0] = 0, F[1] = 1, F[n] = F[n − 1] + F[n-2],对于 n ≥ 2.

给定一个整数n,你需要求出 F[n] 的后四位。

输入格式:

有多组测试数据,每组测试数据包含一个整数 n(0 ≤ n ≤ 1e9)。整数 -1 代表输入结束。

输出格式:

输出每组数据 F[n] 的最后四位。

如果 F[n] 最后四位全是0,输出“0”;否则,忽略任何前导的0(即输出 F[n] mod 10000)。

输入样例:

0
9
999999999
1000000000
-1

输出样例:

0
34
626
6875
  • 分析

数据范围较大,如果递推会出现超时,那么可以使用矩阵优化

[ F ( n ) F ( n − 1 ) ] ∗ [ 1 1 1 0 ] = [ F ( n ) + F ( n − 1 ) F ( n ) ] = [ F ( n + 1 ) F ( n ) ] [ F ( n ) F ( n − 1 ) ] = [ f ( 2 ) f ( 1 ) ] ∗ [ 1 1 1 0 ] n − 2 \begin{aligned} \left [ \begin{matrix} F(n) & F(n-1) \end{matrix} \right ] * \left [ \begin{matrix} 1 & 1 \\ 1 & 0 \end{matrix} \right ] &=\left [ \begin{matrix} F(n) + F(n-1) & F(n) \end{matrix} \right ] \\ &=\left [ \begin{matrix} F(n+1) & F(n) \end{matrix} \right ] \\ \quad \\ \left [ \begin{matrix} F(n) & F(n-1) \end{matrix} \right ] &= \left [ \begin{matrix} f(2) & f(1) \end{matrix} \right ] * \left [ \begin{matrix} 1 & 1 \\ 1 & 0 \end{matrix} \right ] ^{n-2} \end{aligned} [F(n)F(n1)][1110][F(n)F(n1)]=[F(n)+F(n1)F(n)]=[F(n+1)F(n)]=[f(2)f(1)][1110]n2

  • 参考程序
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define int long long
const int mod = 1e4, N=10;
struct Matrix {
    int l,r,data[N][N];
    Matrix(int a,int b):l(a), r(b) {
        memset(data, 0, sizeof(data));
    }
    Matrix operator+ (const Matrix& t) const {
        Matrix c(l, r);
        for(int i=1; i<=l; i++)
            for(int j=1; j<=r; j++)
                c.data[i][j] = (data[i][j]+t.data[i][j])%mod;
        return c;
    }
    Matrix operator- (const Matrix& t) const {
        Matrix c(l, r);
        for(int i=1; i<=l; i++)
            for(int j=1; j<=r; j++)
                c.data[i][j] = (data[i][j]-t.data[i][j])%mod;
        return c;
    }
    Matrix operator* (int k) const {
        Matrix c(l, r);
        for(int i=1; i<=l; i++)
            for(int j=1; j<=r; j++)
                c.data[i][j] = (k*data[i][j])%mod;
        return c;
    }
    Matrix operator* (const Matrix& t) const {
        Matrix c(l, t.r);
        for(int  k=1; k<=t.l; k++)
            for(int i=1; i<=c.l; i++)
                for(int j=1; j<=c.r; j++)
        c.data[i][j] = (c.data[i][j]+data[i][k]*t.data[k][j]%mod)%mod;
        return c;
    }
    void print() {
        for(int i=1; i<=l; i++) {
            for(int j=1; j<=r; j++) cout<<data[i][j]<<" ";
            cout<<endl;
        }
        cout<<endl;
    }
};

Matrix fastpow(Matrix a, int k) {
    Matrix ans=a;
    while(k) {
        if(k&1) ans=ans*a;
        a = a*a;
        k>>=1;
    }
    return ans;
}
signed main() {
//    freopen("data.in", "r", stdin);
    int n;
    while(~scanf("%lld", &n) && n!=-1) {
        Matrix a(2, 2);
        a.data[1][1] = a.data[1][2] = a.data[2][1] = 1;
        if(n>2) a = fastpow(a, n-2);
        if(n==0) a.data[1][1]=0;
        printf("%lld\n", a.data[1][1]);
    }
    return 0;
}

题目描述

输入格式

输出格式

输入样例


输出样例


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值