zoukankan      html  css  js  c++  java
  • 【noi.ac-CSP-S全国模拟赛第三场】#705. mmt

    给定数组a[],b[]

    求$$c_i=sum_{j=1}^{i} a_{left lfloor frac{n}{j} ight floor}·b_{i mod j}$$

    大概就是对于每一个n求上面那个式子,显然数论分块

    乱搞有$$c_n=sum_{i=1}^{n} a_{left lfloor frac{n}{i} ight floor}·b_{n-lfloor frac{n}{i} floor * i}$$

    当在同一块内,也就是$lfloor frac{n}{i} floor$相等的时候,我们令$t=lfloor frac{n}{i} floor$,左边界为l,右边界为r有:

    $$c_n=a_t*sum_{i=l}^{r}b_{n-t*i}$$

    看了其他巨佬的做法了之后知道了要对b[]按位置的差值做一个前缀和

    所以令f[i][j]表示位置差为j,当前位置为i的前缀和

    然而空间开不下,所以j太大的时候暴力计算就好了(j大的时候显然减个几下就没了)

     1 #include<bits/stdc++.h>
     2 #define int long long
     3 #define writeln(x)  write(x),puts("")
     4 #define writep(x)   write(x),putchar(' ')
     5 using namespace std;
     6 inline int read(){
     7     int ans=0,f=1;char chr=getchar();
     8     while(!isdigit(chr)){if(chr=='-') f=-1;chr=getchar();}
     9     while(isdigit(chr)){ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
    10     return ans*f;
    11 }void write(int x){
    12     if(x<0) putchar('-'),x=-x;
    13     if(x>9) write(x/10);
    14     putchar(x%10+'0');
    15 }const int M = 1e5+5,mod = 123456789;
    16 int a[M],b[M],n,m,s[M][205];
    17 inline int calc(int n,int x,int l,int r){
    18     int ans=0;
    19     if(n/x<=200){
    20         if(l-n/x<0) ans=s[r][n/x];
    21         else ans=s[r][n/x]-s[l-n/x][n/x];
    22         ans=(ans%mod+mod)%mod;
    23     }else{
    24         int y=n/(n/x);
    25         for(int p=x;p<=y;p++)ans=(ans+b[n-p*(n/x)])%mod;
    26     }return ans;
    27 }
    28 inline int Solve(int n){
    29     int ans=0;
    30     for(int i=1,j,t;i<=n;i=j+1){
    31         if(n/i==0)j=n;
    32         else j=n/(n/i);
    33         t=a[n/i]*calc(n,i,n-j*(n/i),n-i*(n/i))%mod;
    34         ans=(ans+t)%mod;
    35     }return ans;
    36 }
    37 signed main(){
    38     n=read();
    39     for(int i=1;i<=n;i++)a[i]=read();
    40     for(int i=0;i<n;i++)b[i]=read();
    41     for(int i=0;i<n;i++)
    42         for(int j=0;j<=200;j++)
    43             if(i-j>=0)s[i][j]=(s[i-j][j]+b[i])%mod;
    44             else s[i][j]=b[i];
    45     for(int i=1;i<=n;i++)printf("%lld
    ",Solve(i));
    46     return 0;
    47 }
  • 相关阅读:
    结对编程:黄金点小游戏
    在win7环境下如何安装Microsoft Visual Studio
    软件工程第一次作业
    Android关于保存数据(Saving data)
    Android bitmap和canvas小记(转)
    java/android开发中删除文件
    博客园的第一篇
    安卓初学者必看实例,(计算圆面积)
    安卓初学者必看实例,(文件管理器简单实现)
    安卓初学者必看实例,(访问sqlite)
  • 原文地址:https://www.cnblogs.com/zhenglw/p/11713223.html
Copyright © 2011-2022 走看看