传送门:QAQQAQ

题意:话说小X在孩提时,都会做标准的蛇形矩阵了,发现很好玩。现在的小X很想对其进行改版,变为如下类型的一个无限大蛇形数阵:

令S(x)表示以1为左上角,x为右下角的矩形内所有数之和。例如S(12)就是具有深色背景的数之和。
给定n,对于“以1为左上角,n为右下角的矩形”内的每一个数i,计算所有S(i)之和。

思路:神仙数学题。。。

先看暴力:我们通过人工YY和简单推算可以得出一个公式:$ans=\sum_{i=1}^{n}\sum_{j=1}^{m}a_{i,j}*\left ( n-i+1 \right )*\left ( m-j+1 \right )$

那么我们可以在$O(n)$的复杂度内解决问题

现在开始优化环节:我们可以把一个给定矩形拆分成若干条链,使每一条链都是一个连续的数列(莫名想到树链剖分。。。)

具体拆分方法为:若是一个长方形,则先把多余的行或列拆出来,把它变成一个正方形。然后对于每一圈,我们先竖着拆$rnd$个,再横着拆$rnd-1$个,拆完为止。

现在我们的任务是求一个连续序列的和。每一个的统计总和为$a_{i,j}*\left ( n-i+1 \right )*\left ( m-j+1 \right )$,而且这个序列一定在同一行或同一列,所以我们可以把$\left ( n-i+1 \right )$或$\left ( m-j+1 \right )$中的一项提取出来,这样剩下的就是两项相乘求和了。而我们发现这两项分别在两个公差为$1$或$-1$的等差数列中。

现在开始数学环节——暴力推公式

令$f(s1,s2,d1,d2,n)$为首项为$s1$,公差为$d1$的等差数列和首项为$s2$,公差为$d2$的等差数列每一项分别相乘,前$n$项乘积的和

即:$f(s1,s2,d1,d2,n)$=$\sum_{i=1}^{n}\left [ s1+\left ( i-1 \right )*d1 \right ]*\left [ s2+\left ( i-1 \right )*d2 \right ]$

          =$\sum_{i=1}^{n}(s1*s2)+\sum_{i=1}^{n}(s1*d2*(i-1))+\sum_{i=1}^{n}( d1*s2*(i-1))+\sum_{i=1}^{n}( d1*d2*(i-1)^{2} )$

          =$n*s1*s2+s1*d2*\sum_{i=1}^{n-1}i+s2*d1*\sum_{i=1}^{n-1}i+d1*d2*\sum_{i=1}^{n-1}i^{2}$

          =$n*s1*s2+s1*d2*\frac{(n-1)*n}{2}+d1*s2*\frac{(n-1)*n}{2}+d1*d2*\frac{(n-1)*n*(2*n-1)}{6}$

那么我们现在就可以用$O(1)$的时间算出每一条链,而一共拆成$\sqrt{n}$条链,所以总复杂度$\sqrt{n}$

代码:(注意代码实现时$x,y$很容易弄混)

#include<bits/stdc++.h>
#define pii pair<ll,ll>
#define mk make_pair
using namespace std;
typedef long long ll;
const ll MOD=(ll)1e9+;
const ll inv2=;
const ll inv6=; pii find(ll x)
{
ll rnd=(ll)sqrt(x);
if(rnd*rnd!=x) rnd++;
ll End=rnd*rnd;
ll dif=End-x;
ll posx,posy;
if(rnd%==)
{
posx=rnd; posy=;
if(dif<=rnd-) posy+=dif;
else
{
posy=rnd; dif-=(rnd-);
posx-=dif;
}
}
else
{
posx=,posy=rnd;
if(dif<=rnd-) posx+=dif;
else
{
posx=rnd; dif-=(rnd-);
posy-=dif;
}
}
return mk(posx,posy);
} void fn(ll &x)
{
x=(x%MOD+MOD)%MOD;
} ll f(ll s1,ll s2,ll d1,ll d2,ll n)
{
if(n==) return ;
ll ret=n*s1%MOD*s2%MOD; fn(ret);
ret=(ret+n*(n-)%MOD*inv2%MOD*(s1*d2%MOD+s2*d1%MOD))%MOD; fn(ret);
ret=(ret+n*(n-)%MOD*(*n-)%MOD*inv6%MOD*d1%MOD*d2%MOD); fn(ret);
return ret;
} int main()
{
ll x,ans=;
scanf("%lld",&x);
pii pos=find(x);
ll n=pos.first,m=pos.second;
ll nowx=n,nowy=m;
while(nowx>m)
{
if(nowx%==)
{
ll k=n-nowx+;
ll s1=(nowx-)*(nowx-)+; ll d1=;
ll s2=m; ll d2=-;
ans=(ans+k*f(s1,s2,d1,d2,m))%MOD;
}
else
{
ll k=n-nowx+;
ll s1=nowx*nowx; ll d1=-;
ll s2=m; ll d2=-;
ans=(ans+k*f(s1,s2,d1,d2,m))%MOD;
}
nowx--;
}
while (nowy>n)
{
if(nowy%==)
{
ll k=m-nowy+;
ll s1=nowy*nowy; ll d1=-;
ll s2=n; ll d2=-;
ans=(ans+k*f(s1,s2,d1,d2,n))%MOD;
}
else
{
ll k=m-nowy+;
ll s1=(nowy-)*(nowy-)+; ll d1=;
ll s2=n; ll d2=-;
ans=(ans+k*f(s1,s2,d1,d2,n))%MOD;
}
nowy--;
}
while(nowx>&&nowy>)
{
if(nowx%==)
{
ll k=m-nowy+;
ll s1=nowy*nowy; ll d1=-;
ll s2=n; ll d2=-;
ans=(ans+k*f(s1,s2,d1,d2,nowx))%MOD;
k=n-nowx+;
s1=(nowx-)*(nowx-)+; d1=;
s2=m; d2=-;
ans=(ans+k*f(s1,s2,d1,d2,nowy-))%MOD;
}
else
{
ll k=m-nowy+;
ll s1=(nowy-)*(nowy-)+; ll d1=;
ll s2=n; ll d2=-;
ans=(ans+k*f(s1,s2,d1,d2,nowx))%MOD;
k=n-nowx+;
s1=nowx*nowx; d1=-;
s2=m; d2=-;
ans=(ans+k*f(s1,s2,d1,d2,nowy-))%MOD;
}
nowx--; nowy--;
}
cout<<ans<<endl;
return ;
}

夏令营501-511NOIP训练17——蛇形矩阵的更多相关文章

  1. XJOI 夏令营501-511NOIP训练17 蛇形数阵

    话说小X在孩提时,都会做标准的蛇形矩阵了,发现很好玩.现在的小X很想对其进行改版,变为如下类型的一个无限大蛇形数阵:令S(x)表示以1为左上角,x为右下角的矩形内所有数之和.例如S(12)就是具有深色 ...

  2. EOJ3536 求蛇形矩阵每一行的和---找规律

    题目链接: https://acm.ecnu.edu.cn/problem/3536/ 题目大意: 求蛇形矩阵的每一行的和,数据范围n<=200000. 思路: 由于n数据较大,所以感觉应该是需 ...

  3. EOJ 3.30 B. 蛇形矩阵【找规律/待补】

    [链接]:https://acm.ecnu.edu.cn/contest/59/problem/B/ B. 蛇形矩阵 Time limit per test: 2.0 seconds Memory l ...

  4. js实现蛇形矩阵

    参加腾讯前端实习生笔试,真的是被虐了千百遍,除了一条js程序题,其他半点前端都没有,都是考算法,计算机原理,数据结构.下面贴上腾讯笔试最后三大条中的一条,实现一个蛇形矩阵的输出.蛇形矩阵的什么样这里我 ...

  5. 【面试】输出"蛇形"矩阵

    一.题目描述 腾讯实习在线笔试的一道题目. 根据输入的数字(< 1000),输出这样的"蛇形"矩阵,如下.输入n,输出(n * n)阶矩阵,满足由外到内依次增大. 如: 输入 ...

  6. c++实现蛇形矩阵总结

    蛇形矩阵,百度了一下,是这么一个东西: 像一条蛇一样依次递增. 我想,竟然做了螺旋矩阵,那做一下这个吧.在之前的螺旋矩阵的main函数基础上,写个函数接口就行了,这一次做的很快,但是这个矩阵感觉比螺旋 ...

  7. wikioi 1160 蛇形矩阵

    /*======================================================================== 1160 蛇形矩阵 题目描述 Descriptio ...

  8. Java编码 蛇形矩阵的构建与遍历输出

    一.蛇形矩阵的构建,并按行输出 例: 输入:n, 生成n*n的蛇形矩阵 1 2 3 8 9 4 7 6 5 输出:1 2 3 8 9 4 7 6 5 java编码 public static void ...

  9. c++打印蛇形矩阵

    一个m*n的矩阵里按照下图形式填充,最后形成的矩阵即为蛇形矩阵,下图是m=4, n =5时的蛇形矩阵: 方法一:逐层循环 #include <iostream> using namespa ...

随机推荐

  1. Codeigniter Session: Configured save path is not a directory

    Codeigniter 3.x Message: Session: Configured save path '' is not a directory, doesn't exist or canno ...

  2. IDEA使用maven插件打jar包流程

    idea使用maven插件打jar包步骤以及遇到的问题 idea自带了maven工具,idea右边点击maven选项: 一.在pom中添加插件,直接复制就好,如下选项 <plugin> & ...

  3. wordpress翻译插件gtranslate

    https://www.gdstautoparts.com/

  4. css制作旋转风车(transform 篇)

    做这个案例之前首先要大概了解CSS的transform的属性 transform 属性向元素应用 2D 或 3D 转换.该属性允许我们对元素进行旋转.缩放.移动或倾斜. 看看效果图 打开的时候自动旋转 ...

  5. 树状数组优化dp——cf985E经典

    /* dp[i]=0|1 表示前i是否可以被成功分组, dp[i+1]能够变成1的三个条件 1:j∈[0,i-k]里存在dp[j]=1 2:dp[j]=1 3:a[i+1]-a[j+1]<=d ...

  6. AtCoder ARC061E Snuke's Subway Trip 最短路

    目录 Catalog Solution: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 Catalog Problem:传送门  Portal  原题目描述在最下面.  \(n(1 ...

  7. 微信-小程序-开发文档-服务端-模板消息:templateMessage.getTemplateLibraryById

    ylbtech-微信-小程序-开发文档-服务端-模板消息:templateMessage.getTemplateLibraryById 1.返回顶部 1. templateMessage.getTem ...

  8. 完美解决 IE6 position:fixed 固定定位问题

    关于 position:fixed; 属性 生成绝对定位的元素,相对于浏览器窗口进行定位. 元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定. pos ...

  9. 整理及优化CSS代码的7个原则

    作为网页设计师(前端工程师),你可能还记得曾经的那个网页大小建议:一个网页(包括HTML.CSS.Javacript.Flash和图片)尽量不要超过30KB的大小,随着互联网的日益庞大,网络带宽也在飞 ...

  10. C++之控制内存分配

    一.内存分配方式 在C++中,内存分成5个区,他们分别是堆.栈.自由存储区.全局/静态存储区和常量存储区.栈:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释 ...