zoukankan      html  css  js  c++  java
  • 求和

    Problem description

    问题描述

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

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

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

    Input format

    第一行是用一个空格隔开的两个正整数n和m,n表纸带上格子的个数,m表纸带上颜色的种类数。
      第二行有n用空格隔开的正整数,第i数字number表纸带上编号为i格子上面写的数字。
      第三行有n用空格隔开的正整数,第i数字color表纸带上编号为i格子染的颜色。

    Output format

    共一行,一个整数,表示所求的纸带分数除以10,007所得的余数。

    Algorithm design

    Simple enumeration + Mathematics deal

    Problem analysis

    核心:数据分离

    N太大 直接搞O(N2)

    读题

    x<y<z,y-x=z-y,colorx=colorz
    翻译一下

    x,z奇偶性相同且同种颜色

    那么把n拆成两条链:奇数链,偶数链,两链互不相干

    对于链上所有同种颜色的点 都可以求分数

    既然如此再看

    (x+z)*(number_x+number_z)

    拆解后

    x*num_x+z*num_z+x*num_z+z*num_x

    前缀和思想

    取一点x 那么关于x的所有三元组的分数之和

    x*num_x*cnt_others + sumcnt_others + x*numcnt_others + num_x*idcnt_others

    所以只需要分两条链

    枚举每个点

    根据其颜色进行处理

    O(2n)

    Anyway

    把cnt处理完了再搞会有一倍冗出

    所以边枚举边搞最好

    先前忘了这点愣了几分钟

    错误记录

    1.没把ans求余

    2.没考虑sum也很大也要求余

    3.即使执行上述操作 sum还是很大 所以开ll

    Source code

     1 #include <bits/stdc++.h>
     2 #define F(i,j,k) for(int i=j;i<=k;i++)
     3 #define D(i,j,k) for(int i=j;i>=k;i--)
     4 #define sc(i) scanf("%lld",&i)
     5 #define mo 10007
     6 #define ll long long
     7 #define R return
     8  
     9 using namespace std;
    10  
    11 int n,m;
    12 llans,num[100010],col[100010],sumnu[100010],sum[100010],sumid[100010],cnt[100010];
    13  
    14 void read()
    15 {
    16    cin>>n>>m;
    17    F(i,1,n)sc(num[i]);
    18    F(i,1,n)sc(col[i]);
    19    R;
    20 }
    21  
    22 void work()
    23 {
    24    F(jff,1,2)
    25    {
    26       memset(sumid,0,sizeof(sumid));
    27       memset(sumnu,0,sizeof(sumnu));
    28       memset(sum,0,sizeof(sum));
    29       memset(cnt,0,sizeof(cnt));
    30       for(int i=jff;i<=n;i+=2)
    31       {
    32          ans=(ans+sum[col[i]]+num[i]*i*cnt[col[i]])%mo;
    33          ans=(ans+sumnu[col[i]]*i)%mo;
    34          ans=(ans+sumid[col[i]]*num[i])%mo;
    35 //通过前缀和计算 将结果数添加
    36          sumid[col[i]]=(sumid[col[i]]+i)%mo;
    37          sumnu[col[i]]=(sumnu[col[i]]+num[i])%mo;
    38          sum[col[i]]=(sum[col[i]]+num[i]*i)%mo;
    39 //像前面说的边推进边处理所有前缀和
    40       }
    41    }
    42    cout<<ans<<endl;
    43    R;
    44 }
    45  
    46      
    47  
    48 int main()
    49 {
    50    freopen("sum.in","r",stdin);
    51    freopen("sum.out","w",stdout);
    52    read();
    53    work();
    54    R 0;
    55 }
    56  
    View Code

    over

  • 相关阅读:
    VMware安装Linux时'Operating System Not Found'的解决方法
    [NLP自然语言处理]谷歌BERT模型深度解析
    【NPM】npm ERR! Unexpected end of JSON input while parsing near '...",'解决方案
    【前端基础系列】slice方法将类数组转换数组实现原理
    【读书笔记】理解基本排序算法
    【读书笔记】《人工智能简史》
    【前端基础系列】理解bind方法使用与实现
    【前端基础系列】理解GET与POST请求区别
    HTTPS工作原理
    微信WebView关闭后本地cookie无法清除问题
  • 原文地址:https://www.cnblogs.com/qswx/p/9155674.html
Copyright © 2011-2022 走看看