zoukankan      html  css  js  c++  java
  • 洛谷 P2671 求和

    题目描述

    一条狭长的纸带被均匀划分出了(n)个格子,格子编号从(1)(n)。每个格子上都染了一种颜色(color\_i)([1,m])当中的一个整数表示,并且写了一个数字(number\_i)

    定义一种特殊的三元组:((x,y,z)),其中(x,y,z)都代表纸带上格子的编号,这里的三元组要求满足以下两个条件:

    (x,y,z)是整数,(x<y<z,y-x=z-y)

    (color_x)=(color_z)

    满足上述条件的三元组的分数规定为((x+z) imes(number\_x+number\_z))。整个纸带的分数规定为所有满足条件的三元组的分数的和。这个分数可能会很大,你只要输出整个纸带的分数除以(10,007)所得的余数即可。

    输入格式

    第一行是用一个空格隔开的两个正整数(n)(m)(n)表示纸带上格子的个数,(m)表纸带上颜色的种类数。

    第二行有(n)用空格隔开的正整数,第(i)数字(number)表纸带上编号为(i)格子上面写的数字。

    第三行有(n)用空格隔开的正整数,第(i)数字(color)表纸带上编号为(i)格子染的颜色。

    输出格式

    一个整数,表示所求的纸带分数除以(10007)所得的余数。

    输入输出样例

    输入 #1

    6 2
    5 5 3 2 2 2
    2 2 1 1 2 1
    

    输出 #1

    82
    

    输入 #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, 3, 5), (4, 5, 6))

    所以纸带的分数为((1 + 5) imes (5 + 2) + (4 + 6) imes (2 + 2) = 42 + 40 = 82)

    对于第 (1) 组至第 (2) 组数据, (1 ≤ n ≤ 100, 1 ≤ m ≤ 5)

    对于第 (3) 组至第 (4) 组数据, (1 ≤ n ≤ 3000, 1 ≤ m ≤ 100)

    对于第 (5) 组至第 (6) 组数据, (1 ≤ n ≤ 100000, 1 ≤ m ≤ 100000),且不存在出现次数超过$20$20的颜色;

    对 于 全 部 (10) 组 数 据 , (1 ≤ n ≤ 100000, 1 ≤ m ≤ 100000, 1 ≤ color\_i ≤ m,1≤number\_i≤100000)

    思路

    我离做出这个题只差一步化简式子然后优化了,但还是没有想到。

    其实前面的思路比较好想,暴力当然就是(O(n^2))两层循环枚举,如果两个数颜色和奇偶性都相同,那就加和((y-x=z-y)其实就是(x+z=2y),所以奇偶性相同)。但是这样只能得到(40pts),要思考正解。

    通过两层循环可以发现,我们其实不需要管中间那个点是什么,只要确定两边的点即可。而两边的点又满足颜色相同和奇偶性相同,我们就可以把所有的格子分成(2m)段,每一种颜色的奇数号和偶数号分开,就有这么多段。会发现,在段内任意选两个数,都是满足题意的,就加和。但如果分开后还是暴力循环相当于没有任何优化,我就是卡在了这里。但是我们可以将式子写出来,然后化简,寻找优化的方法。

    以其中一段为例,比如有一段里面有(k)个格子。然后第(i)个格子的值是(x_i),编号是(y_i),那么对答案的贡献就是

    (x1+x2)*(y1+y2)+(x1+x3)*(y1+y3)+...+(x1+xk)*(y1+yk)+
    (x2+x3)*(y2+y3)+(x2+x4)*(y2+y4)+.........
    

    然后我们随便取个(k),然后用手化简两组样例,就会发现这样的规律:

    原式 = x1*(y1*(k-1)+y2+y3+...+yk)+x2*(y2*(k-1)+y1+y3+...+yk)+...... 
    上式 = x1*(y1*(k-2)+y1+y2+...+yk)+x2*(y2*(k-2)+y1+y2+...+yk)+......
    

    这样的话,我们只需要预处理出前缀和,然后扫一遍一开始的序列即可,时间复杂度为(O(n))

    代码

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    using namespace std;
    typedef long long int ll;
    const int mod=10007;
    int n,m,ans; 
    int tot[200005],num[100005],color[100005],sum[200005];
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&num[i]);
    	}
    	for(int i=1;i<=n;i++){
    		scanf("%d",&color[i]);
    	}
    	for(int i=1;i<=n;i++){
    		if(i%2==0){
    			tot[color[i]]++;//记录单数颜色那一段的个数
    			sum[color[i]]=(sum[color[i]]+i)%mod;//预处理前缀和 
    		}
    		else{
    			tot[color[i]+m]++;//+m防止重复,记录偶数颜色个数
    			sum[color[i]+m]=(sum[color[i]+m]+i)%mod;//预处理前缀和
    		}
    	}
    	for(int i=1;i<=n;i++){
    		if(i%2==0){
    			ans=(ans+num[i]*(i*(tot[color[i]]-2)%mod+sum[color[i]]))%mod;//套用公式
    		}
    		else{
    			ans=(ans+num[i]*(i*(tot[color[i]+m]-2)%mod+sum[color[i]+m]))%mod;
    		}
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    python3 TypeError: a bytes-like object is required, not 'str'
    Centos 安装Python Scrapy PhantomJS
    Linux alias
    Vim vimrc配置
    Windows下 Python Selenium PhantomJS 抓取网页并截图
    Linux sort
    Linux RSync 搭建
    SSH隧道 访问内网机
    笔记《鸟哥的Linux私房菜》7 Linux档案与目录管理
    Tornado 错误 "Global name 'memoryview' is not defined"
  • 原文地址:https://www.cnblogs.com/57xmz/p/13544076.html
Copyright © 2011-2022 走看看