首页 > 代码库 > 发个题目坑 二模03day1

发个题目坑 二模03day1

1.数列(seq2.pas/c/cpp)

题目描述

一个数列定义如下:f(1) = 1,f(2) = 1,f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7。给定 A,B 和 n 的值,要求计算 f(n)的值。

输入格式

仅一行包含 3 个整数 A,B 和 n,其中(1≤ A, B ≤1000, 1 ≤n≤100,000,000)。

输出格式

仅一行,一个整数,即 f(n)的值。

输入输出样例

input:                 |  output:
-----------------------------------
1 1 3 | 2
-----------------------------------
1 2 10 | 5

分析

这是一道比较有意思的题目,虽然比较水,AC算法也不是每人都能想到的啦啦啦.
首先看到输出的数据范围,非常小对不对!$0\le f(n)\le 6$.然后研究这个递推数列的性质.它是一个线性递推数列,也就是可以用矩阵快速幂做.但是这样还是太麻烦了呢.
注意到这个数列像极了Fibonacci数列,嗯,让我们称它为"Coefficient Extended Fibonacci Sequence of Natural Numbers",附个简称叫CEFSNN.虽然这没什么用啊...也是装逼利器对不~
把求f(n)的表达式换一个写法会怎么样呢?
f(n)=((A*f(n-1))mod 7+(B*f(n-2))mod 7)mod 7
然后A,B都是常量嗯.
那么因为 A*f(n-1)mod 7=(A mod 7)*(f(n-1)mod 7)mod 7 嗯,B...同理
A mod 7 也是常量吖.
那么设两个数$x,y \in \mathbb{N}$,只要$f(x)\equiv f(y) \pmod{7}$且$f(x+1)\equiv f(y+1) \pmod{7}$则x与y之间就是一个循环节.
因为前后两个数排列最多49种,寻找循环节长度不会超过49.(如果超过根据鸽笼原理可知肯定有一个更小的循环节,且有一个显然的结论即是若a和b都可作为循环节长度,则gcd(a,b)也可以.扯远了)
这题正解应该就是这个了.
当然有兴趣试试Matrix Multiplication哈.

代码

因为逗逼的po主是先写题解再写题目的所以...(不拿代码讲算法都是耍流氓!!)哎别打我!!我写个不成吗? 
#include "cstdio"int a,b,n,i,p,f[60];bool h[80];int main(){	freopen("seq2.in","r",stdin);	freopen("seq2.out","w",stdout);	scanf("%d%d%d",&a,&b,&n);	a%=7;	b%=7;	f[1]=f[2]=1;	h[9]=true;	for(i=3;i<52;++i){		f[i]=(a*f[i-1]+b*f[i-2])%7;		if(n==i){			printf("%d\n",f[i]);			return 0;		}		if(h[f[i]*8+f[i-1]]){			p=i-2;			break;		}else{			h[f[i]*8+f[i-1]]=true;		}	}	printf("%d\n", f[(n-1)%p+1]);	return 0;}

2.最长路(path.pas/c/cpp)

题目描述

设 G 为有 n 个顶点的有向无环图,G 中各顶点的编号为 1 到 n,且当<i,j>为 G 中的一条边时有i < j。设 w(i,j)为边<i,j>的长度,请设计算法,计算图 G 中<1,n>间的最长路径。

输入数据

第一行有两个整数 n 和 m,表示有 n 个顶点和 m 条边,其中(2≤n≤1500,m≤50000),接下来 m 行中每行输入 3 个整数 a ,b,v 表示从 a 点到 b 点有条边,边的长度为 v。

输出数据

一个整数,即 1 到 n 之间的最长路径.如果 1 到 n 之间没连通,输出-1。

输入输出样例

input:                 |  output:
-----------------------------------
2 1 |
1 2 1 | 2

题解

良心傻逼题.因为是有向无环图,SFPA大胆做.注意判断连通性和是求最长路.

代码

话说这是一次通过的节奏?但要是我连SPFA都写错我还怎么有脸混OI界?
#include <cstdio>int next[70000],to[70000],hl,head[3000],le[70000];inline void addEdge(int f,int t,int v){	++hl;	next[hl]=head[f];	to[hl]=t;	le[hl]=v;	head[f]=hl;}int i,j,k,l,a,b,c,m,n;int qh,qt,q[600000],f[3000];bool iq[3000],vis[3000];void spfa(){	vis[1]=iq[1]=true;	qt=2;	qh=1;	q[1]=1;	while(qh!=qt){		i=q[qh];		iq[i]=false;		for(j=head[i];j!=0;j=next[j]){			vis[k=to[j]]=true;			l=le[j];			if(f[i]+l>f[k]){				f[k]=f[i]+l;				if(!iq[i]){					iq[i]=true;					q[qt++]=k;				}			}		}		++qh;	}}int main(int argc, char const *argv[]){	freopen("path.in","r",stdin);	freopen("path.out","w",stdout);	scanf("%d%d",&n,&m);	for(i=0;i<m;++i){		scanf("%d%d%d",&a,&b,&c);		addEdge(a,b,c);	}	spfa();	if(!vis[n]){		printf("-1\n");	}else{		printf("%d\n", f[n]);	}	return 0;}

发个题目坑 二模03day1