NOIP2015 T3 求和 乱作题解
题目
题目背景
NOIP2015 普及组 T3
题目描述
一条狭长的纸带被均匀划分出了
定义一种特殊的三元组:
-
是整数, -
满足上述条件的三元组的分数规定为
输入格式
第一行是用一个空格隔开的两个正整数
第二行有
第三行有
输出格式
一个整数,表示所求的纸带分数除以
样例 #1
样例输入 #1
6 2
5 5 3 2 2 2
2 2 1 1 2 1
样例输出 #1
82
样例 #2
样例输入 #2
15 4
5 10 8 2 2 2 9 9 7 7 5 6 4 2 4
2 2 3 3 4 3 3 2 4 4 4 4 1 1 1
样例输出 #2
1388
提示
【输入输出样例 1 说明】
纸带如题目描述中的图所示。
所有满足条件的三元组为:
所以纸带的分数为
对于第
对于第
对于第
对 于 全 部
看起来好像不是很难啊,为什么我做不出来呢;
1. 暴力枚举
枚举x,y,z的值,再判断是否符合条件 ;
时间复杂度:
期望得分:
#include <bits/stdc++.h>
using namespace std;
const int N=100010;
long long n,m,ans;
long long color[N],number[N];
int main()
{
scanf("%lld %lld",&n , &m);
for(int i=1 ; i<=n ; i++) scanf("%lld",&number[i]);
for(int i=1 ; i<=n ; i++) scanf("%lld",&color[i]);
for(int x=1 ; x<=n ; x++)
{
for(int y=x+1 ; y<=n ; y++)
{
for(int z=y+1 ; z<=n ; z++)
{
if( color[x] == color[z] && y-x == z-y )
ans += (x+z) * (number[x] + number[z]);
}
}
}
printf("%lld",ans%10007);
}
2.优化暴力枚举
整理条件(
也就是说,我们可以通过枚举x,z的值来确定y的值
时间复杂度:
期望得分:
#include <bits/stdc++.h>
using namespace std;
const int N=100010;
long long n,m,ans;
long long color[N],number[N];
int main()
{
scanf("%lld %lld",&n , &m);
for(int i=1 ; i<=n ; i++) scanf("%lld",&number[i]);
for(int i=1 ; i<=n ; i++) scanf("%lld",&color[i]);
for(int x=1 ; x<=n ; x++)
{
for(int z=x+2 ; z<=n ; z+=2)
{
int y=(x+z)/2;
if(color[x] == color[z])
ans += (x+z) * (number[x] + number[z]);
}
}
printf("%lld",ans%10007);
}
3.正解
仔细观察这个式子
因为
所以
也就是说
再想想题目(
◝(⑅•ᴗ•⑅)◜..°♡ 欸!!瞧瞧我们发现了什么!
整理一下
这个时候我们就要运用分组思想
————那么 什么是分组思想?
分组思想,就是把具有相同性质的两个集合放在一起,方便计算。
————沃兹·基朔德
放在这题里就是
先将所有数字按颜色分组,再按奇偶分组(其实先按什么分都一样的啦
显然,每一组中,任意一对x,z都可以构造出一个符合条件的三元组(
推式子时间到!
我们不知道从哪搞来了两个数组a,number;
- a[i]表示某一组内第i个格子的编号
- number[i]表示某一组内第i个格子表上写的数字
- k表示组内共有k个格子
那么这个组内的分数应该为
化简一下可得
至于计算
那么整张纸条的分数就是将所有分出来的组的分数的总和!!!
有了思路,写代码清晰无比;
时间复杂度:
期望得分:
#include <bits/stdc++.h>
using namespace std;
const int NN=100010;
const int MOD = 10007;
long long number[NN] ,color[NN];
long long sum[NN][2] , k[NN][2];//sum是前缀和数组,k是每组的个数
long long n,m,ans;
int main()
{
scanf("%d %d" , &n , &m);
for(int i=1 ; i<=n ; i++) scanf("%d",&number[i]);
for(int i=1 ; i<=n ; i++) scanf("%d",&color[i]);
for(int i=1 ; i<=n ; i++)
{
k[color[i]][i%2] ++;
sum[color[i]][i%2] = (sum[color[i]][i%2] + number[i]) % MOD;
}
for(int i=1 ; i<=n ; i++)
{
ans += i * (number[i] * (k[color[i]][i%2]-2) + sum[color[i]][i%2] );
ans %= MOD;
}
printf("%d",ans);
return 0;
}
By Hu_taooo
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现