【LGR-055】洛谷11月月赛总结

出现了!暴力AC!
今天打的这个是信心赛,感觉真的很不错

比赛地址

T1:终于结束的起点
终于结束的起点
终于写下句点
终于我们告别
终于我们又回到原点
……

一个个 OIer 的竞赛生涯总是从一场 NOIp 开始,大多也在一场 NOIp 中结束,好似一次次轮回在不断上演。
如果这次 NOIp 是你的起点,那么祝你的 OI 生涯如同夏花般绚烂。
如果这次 NOIp 是你的终点,那么祝你的 OI 回忆宛若繁星般璀璨。
也许这是你最后一次在洛谷上打比赛,也许不是。
不过,无论如何,祝你在一周后的比赛里,好运。

当然,这道题也和轮回有关系。

题目描述
广为人知的斐波拉契数列f(n) 是这么计算的
在这里插入图片描述

也就是 0, 1, 1, 2, 3, 5, 8, 13⋯,每一项都是前两项之和。

小 F 发现,如果把斐波拉契数列的每一项对任意大于 11 的正整数 MM 取模的时候,数列都会产生循环。

当然,小 F 很快就明白了,因为斐波拉契数列膜M时最多只有 M ^ 2种取值,所以在 M ^ 2次计算后一定出现过循环。

甚至更一般地,我们可以证明,无论取什么模数 M,最终模 M 下的斐波拉契数列都会是 0, 1, 0,1,⋯。

现在,给你一个模数 M,请你求出最小的 n > 0,使得 f(n) mod M = 0, f(n + 1) mod M = 1
输入输出格式
输入格式:
输入一行一个正整数 MM。

输出格式:
输出一行一个正整数 nn。

输入输出样例
输入样例#1:
2
输出样例#1:
3
输入样例#2:
6
输出样例#2:
24
说明
样例 1 解释
斐波拉契数列为 0, 1, 1, 2, 3, 5, 8, 13, 21, 34,⋯,在对 22 取模后结果为 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, ⋯。

我们可以发现,当 n = 3 时,f(n) mod 2= 0, f(n + 1) mod 2 = 1,也就是我们要求的 n 的最小值。

数据范围
对于 30%30% 的数据,M≤18;

对于 70%70% 的数据,M≤2018;

对于 100%100% 的数据,2≤M≤706150=0xAC666。

题解:
暴力100分,自行递推+取模

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
int xx;int ff;char ch;
inline int read(){
	ff=1;
	xx=0;ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')ff=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		xx=(xx<<1)+(xx<<3)+ch-'0';
		ch=getchar();
	}
	return xx*ff;
}
int n;
int f1,f2;
int main(){
	n=read();
	int tar=2;
	int tp;
	f1=1;f2=2;
	while(!((f1%n==0)&&(f2%n==1))){
		tp=(f1+f2)%n;
		f1=f2;f2=tp;
		++tar;
	}
	printf("%d\n",tar);
	return 0;
}

T2: 跳跳!
题目描述
你是一只小跳蛙,你特别擅长在各种地方跳来跳去。

这一天,你和朋友小 F 一起出去玩耍的时候,遇到了一堆高矮不同的石头,其中第 i块的石头高度为 h_i ,地面的高度是 h_0 = 0。你估计着,从第 i 块石头跳到第 j 块石头上耗费的体力值为 (h_i - h_j) ^ 2,从地面跳到第 ii块石头耗费的体力值是 (h_i) ^ 2。
为了给小 F 展现你超级跳的本领,你决定跳到每个石头上各一次,并最终停在任意一块石头上,并且小跳蛙想耗费尽可能多的体力值。

当然,你只是一只小跳蛙,你只会跳,不知道怎么跳才能让本领更充分地展现。

不过你有救啦!小 F 给你递来了一个写着 AK 的电脑,你可以使用计算机程序帮你解决这个问题,万能的计算机会告诉你怎么跳。

那就请你——会写代码的小跳蛙——写下这个程序,为你 NOIp AK 踏出坚实的一步吧!

输入输出格式
输入格式:
输入一行一个正整数 n,表示石头个数。

输入第二行 n 个正整数,表示第 i块石头的高度 h_i。

输出格式:
输出一行一个正整数,表示你可以耗费的体力值的最大值。

输入输出样例
输入样例#1:
2
2 1
输出样例#1:
5
输入样例#2:
3
6 3 5
输出样例#2:
49
说明
样例解释
两个样例按照输入给定的顺序依次跳上去就可以得到最优方案之一。

数据范围
对于 1≤i≤n,有 0 < h_i < 10^4,且保证 h_i互不相同。

对于10% 的数据,n≤3;

对于20% 的数据,n≤10;

对于50% 的数据,n≤20;

对于80% 的数据,n≤50;

对于100% 的数据,n≤300。

题解:
贪心,每一次取出一组最大/最小的,计算答案

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
int xx;int ff;char ch;
inline int read(){
	ff=1;
	xx=0;ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')ff=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		xx=(xx<<1)+(xx<<3)+ch-'0';
		ch=getchar();
	}
	return xx*ff;
}
int n;
int a[310];
bool vis[310];
int main(){
	n=read();
	 ll maxid=0; 
	a[0]=-1;
	for(int i=1;i<=n;++i){
		a[i]=read();
		if(a[i]>a[maxid])maxid=i;
	}
	ll ans=a[maxid]*a[maxid];
	int now=maxid;
	bool ismin=1;
	vis[now]=1;
	for(int i=1;i<n;++i){
		maxid=0;
		if(ismin){
			a[0]=2147483647;
			for(int i=1;i<=n;++i){
				if(vis[i])continue;
				if(a[i]<a[maxid])maxid=i;
			}
		}else{
			a[0]=-1;
			for(int i=1;i<=n;++i){
				if(vis[i])continue;
				if(a[i]>a[maxid])maxid=i;
			}
		}
		ans+=(ll)(a[maxid]-a[now])*(a[maxid]-a[now]);
		now=maxid;
		vis[now]=1;
		ismin^=1;
	}
	
	printf("%lld\n",ans);
	return 0;
}

一开始我想成了最短路。。然后比赛爆零了。。还是不要想太多
T3:咕咕咕
题面
题解:
70pts:枚举子集,从顶DFS到底~~(一开始忘了long long然后只有30。。。)~~

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
using namespace std;
#define MM 100010
#define ll long long

int xx;char ch;
inline int read(){
	xx=0;ch=getchar();
	while(ch<'0'||ch>'9'){
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		xx=(xx<<1)+(xx<<3)+ch-'0';
		ch=getchar();
	}
	return xx;
}
map <int,int> d;
int n,m;
int b[MM];
int c[MM];
int a;
ll ans=0;
//inline void check(){
	//
	//for(int i=1;i<=n;++i)cerr<<a[i];
	//cerr<<endl;
	//
	/*for(int i=1;i<=m;++i){
			bool flag=1;
			for(int j=1;j<=n;++j){
				if(b[i][j]!=a[j]){
					flag=0;
					break;
				}
			}
			if(flag){
				ans+=c[i];
				break;
			}
		}*/
//}
inline void pr(int i,int dep){
	if(dep<n){
		pr(i>>1,dep+1);
	}
	cerr<<(i&1);
	if(dep==1)cerr<<endl;
/*	for(int j=1;j<=n;i>>=1,++j){
		cerr<<(i&1);
	}
	cerr<<endl;*/
}
ll f[1<<22];
ll ff[1<<22];
#define mo 998244353
inline ll dfs(int state){
	if(f[state]!=-1){
		return f[state];
	}
	ll js=0;
	ff[state]=1;
	js=d[0];
	for(int x=(state-1)&state;x;x=(x-1)&state){
		js=(js+dfs(x))%mo;
		ff[state]=(ff[state]+ff[x])%mo;
	}
	js+=(ff[state]*d[state])%mo;
	f[state]=js%mo;
	
	/*pr(state,1);
	cerr<<"+"<<endl;
	for(int x=(state-1)&state;x;x=(x-1)&state){cerr<<"+"<<endl;}
	cerr<<"ans + = "<<js<<"  "<<d[state]<<endl;*/
	return f[state];
}
int main(){
	n=read();m=read();
	memset(f,-1,sizeof(f));
	for(int i=1;i<=m;++i){
		
			b[i]=0;
			ch=getchar();
			while(ch<'0'||ch>'9')ch=getchar();
			while(ch>='0'&&ch<='9'){
				b[i]=(b[i]<<1)+ch-'0';
				ch=getchar();
			}
		//pr(b[i]);
		//cerr<<b[i]<<endl;
		c[i]=read();
		d[b[i]]=c[i];
	}
	d[0]%=mo;
	a=0;
	for(int i=1;i<=n;++i){a=(a<<1)+1;}
	printf("%lld\n",dfs(a)%mo);
	return 0;
}

正解是推公式递推

T4:不围棋
题面
我写的暴力只有14分。。
正解直接模拟,并查集维护联通块

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值