夏令营501-511NOIP训练17——蛇形矩阵
传送门: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——蛇形矩阵的更多相关文章
- XJOI 夏令营501-511NOIP训练17 蛇形数阵
话说小X在孩提时,都会做标准的蛇形矩阵了,发现很好玩.现在的小X很想对其进行改版,变为如下类型的一个无限大蛇形数阵:令S(x)表示以1为左上角,x为右下角的矩形内所有数之和.例如S(12)就是具有深色 ...
- EOJ3536 求蛇形矩阵每一行的和---找规律
题目链接: https://acm.ecnu.edu.cn/problem/3536/ 题目大意: 求蛇形矩阵的每一行的和,数据范围n<=200000. 思路: 由于n数据较大,所以感觉应该是需 ...
- EOJ 3.30 B. 蛇形矩阵【找规律/待补】
[链接]:https://acm.ecnu.edu.cn/contest/59/problem/B/ B. 蛇形矩阵 Time limit per test: 2.0 seconds Memory l ...
- js实现蛇形矩阵
参加腾讯前端实习生笔试,真的是被虐了千百遍,除了一条js程序题,其他半点前端都没有,都是考算法,计算机原理,数据结构.下面贴上腾讯笔试最后三大条中的一条,实现一个蛇形矩阵的输出.蛇形矩阵的什么样这里我 ...
- 【面试】输出"蛇形"矩阵
一.题目描述 腾讯实习在线笔试的一道题目. 根据输入的数字(< 1000),输出这样的"蛇形"矩阵,如下.输入n,输出(n * n)阶矩阵,满足由外到内依次增大. 如: 输入 ...
- c++实现蛇形矩阵总结
蛇形矩阵,百度了一下,是这么一个东西: 像一条蛇一样依次递增. 我想,竟然做了螺旋矩阵,那做一下这个吧.在之前的螺旋矩阵的main函数基础上,写个函数接口就行了,这一次做的很快,但是这个矩阵感觉比螺旋 ...
- wikioi 1160 蛇形矩阵
/*======================================================================== 1160 蛇形矩阵 题目描述 Descriptio ...
- 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 ...
- c++打印蛇形矩阵
一个m*n的矩阵里按照下图形式填充,最后形成的矩阵即为蛇形矩阵,下图是m=4, n =5时的蛇形矩阵: 方法一:逐层循环 #include <iostream> using namespa ...
随机推荐
- 47. List中特有的方法
集合的体系:--------------| Collection 单列集合的根接口----------| List 如果实现了List接口的集合类,该类具备的特点是:有序,可重复---------- ...
- Java 基础 - JDK 和 JRE 有什么区别
总结 JRE(Java Runtime Environment),就是 Java 运行环境,包括JVM虚拟机(java.exe等)和基本的类库(rt.jar等). JDK (Java Developm ...
- 【Bootstrap】 框架 栅格布局系统设计原理
前提条件(Bootstrap 自带) 首先使用这个布局之前要定义一下代码: 这行代码如果不懂,可以搜索一下,总之大致意思就是,被定义的元素的内边距和边框不再会增加它的宽度,不加入的话排版会有问题. 不 ...
- JavaWeb学习篇之----web应用的虚拟目录映射和主机搭建(Tomcat)
从今天开始来学习JavaWeb的相关知识,之前弄过一段时间JavaWeb的,就是在做毕业设计的时候搞过,但是那时候完全是为了任务去学习,所以效果不好,好多东西都没有深入的研究过,所以接下来的一段时间我 ...
- 约数个数求和+线性筛约数——bzoj3994
这题首先要会线性筛约数个数,并求出前缀和 bool vis[maxn]; int mm,mu[maxn],prime[maxn],num[maxn],sum[maxn],d[maxn],sum1[ma ...
- C++从string中删除所有的某个特定字符【转载】
转载自https://www.cnblogs.com/7z7chn/p/6341453.html C++中要从string中删除所有某个特定字符, 可用如下代码 str.erase(std::remo ...
- C++之string
一.常用操作 二.用“+”连接字符串的注意事项
- 【ARC073F】Many Moves
题目 一个显然的\(dp\),设\(dp_{i,j}\)表示其中一个棋子在\(x_i\)点,另一个棋子在\(j\)点的最小花费 显然\(dp_{i,j}\)有两种转移 第一种是把\(x_i\)上的棋子 ...
- docker删除常见命令
$ docker stop $(docker ps -a | grep "Exited" | awk '{print $1 }') //停止容器 1b7067e19d6f a840 ...
- xwiki系统 知识库 xwiki
1.下载tomcat tar -zxvf apache-tomcat-8.0.14.tar.gz mv apache-tomcat-8.0.14 tomcat-xwiki-8.0 2.下载xwik ...