洛谷P4933 大师 解题报告!

题目描述

n n n 个数构成的数列 a n a_n an ,问其中有多少个等差数列。 n ≤ 1 0 3 , v ≤ 2 × 1 0 4 n \le 10^3 ,v \leq2 \times 10^4 n103v2×104

注意

  • 等差数列的公差可以为负数。
  • 只有一个数时也视为等差数列

输入格式
第一行一个正整数 n n n

第二行 n n n 个非负整数 a [ i ] a[i] a[i]

输出格式
输出一个整数,表示美观的方案数模 998244353 998244353 998244353 的值。

输入输出样例

输入

8
13 14 6 20 27 34 34 41 

输出 50
输入

100
90 1004 171 99 1835 108 81 117 141 126 135 144 81 153 193 81 962 162 1493 171 1780 864 297 180 532 1781 189 1059 198 333 1593 824 207 1877 216 270 225 1131 336 1875 362 234 81 288 1550 243 463 1755 252 406 261 270 279 288 1393 261 1263 297 135 333 872 234 881 180 198 81 225 306 180 90 315 81 81 198 252 81 297 1336 1140 1238 81 198 297 661 81 1372 469 1132 81 126 324 333 342 81 351 481 279 1770 1225 549 

输出 11153

分析:

设数组 b[i][j] 其中i j 分别表示下标和方差,然后进行两重循环枚举(内层循环仍然枚举n,而不是枚举方差,读者可以思考这是为什么)。内层结束之后用栈来统计答案,避免重复统计。

代码:

#include<stdio.h>
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
const int MAXn = 1e4 + 5;
const int MOD =  998244353;
int read(){
	int w = 0, r = 0;char ch = getchar();
	while(ch <'0' || ch > '9')w|=ch == '-', ch = getchar();
	while(ch >= '0' && ch <= '9')r = (r<<1)+(r<<3)+(ch^48), ch = getchar();
	return w ? ~r + 1 : r;
}
int n, a[MAXn], b[1005][40010];
int sta[MAXn], top;
bool vis[40010];
int main(){
	n = read();
	int ans = 0;
	for(int i = 1; i <= n; i++)a[i] = read();
	for(int i = 2; i <= n; i++){
		for(int j = 1; j <= i - 1; j++){
			int variance = a[i] - a[j];
			if(variance < 0)variance += 40005;//处理负数情况
			b[i][variance] += b[j][variance] + 1;//转移方程
			b[i][variance] %= MOD;
		    vis[variance] = 1;
		    sta[++top] = variance;
		}
		do{//栈统计答案
			int p = sta[top--];
			if(vis[p]){
				ans += b[i][p];
				ans %= MOD;
				vis[p] = false;
			}
		}while(top);
	}
	printf("%d", (ans + n)%MOD);
	return 0;
}

后来我看到了别人的代码:

#include <bits/stdc++.h>
using namespace std;
const int MOD=998244353;
int a[1002],f[1002][40002],ans;
int main(){
	int n;cin>>n;
	for(int i=1;i<=n;++i)	scanf("%d",a+i);
	ans=n;
	for(int i=2;i<=n;++i)
		for(int j=1;j<i;++j){
			int d=20000+a[i]-a[j];
			f[i][d]++,ans++;
			if(f[j][d])f[i][d]=(f[i][d]+f[j][d])%MOD,ans=(ans+f[j][d])%MOD;
		}
	cout<<ans%MOD;
}

直接统计了答案没有用栈,简洁美观。
我需要学习的地方还有很多啊,ヾ(◍°∇°◍)ノ゙加油!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值