题目描述

红晕爬上了白玫瑰的花瓣,花刺还没有到达夜莺的心脏,玫瑰的心依旧苍白如终年不化的积雪。由生命铸就的玫瑰不允许存在一丝一毫的瑕疵,假设玫瑰的一片花瓣可以抽象成一个点,一朵玫瑰我们用一个$N\times M$的点阵表示,任意选择其中两个点可以构造出一条$"dead\ line"$。我们需要知道,对于一朵玫瑰,有多少条不同的$"dead\ line"$。两
条$"dead\ line"$不同当且仅当它们不重合,即两条$"dead\ line"$的交点数是有穷的。


输入格式

第一行一个正整数$T$表示数据组数,接下来$T$行,每行两个正整数$N,M$,意义如题。


输出格式

共$T$行,表示这一组数据的答案,答案对$2^{30}$取模。


样例

样例输入:

4
22
7 10
23 34
100 100

样例输出:

6
1111
139395
22791174


数据范围与提示

对于$40%$的数据T≤5,2≤N,M≤40$
对于另外$20%的数据T≤10,2≤N,M≤200$
对于$100%$的数据$T≤10,000,2≤N,M≤4,000$


题解

首先,解释一下题意,$"dead\ line"$是直线,而不是线段。

也就是对于下面这张图,所有的线段是:

所以,我们先来考虑朴素算法。

那么我们发现,只有那些长和宽的$GCD$为$1$的矩形才有可能对答案造成贡献。

但是这样会有重复的,所以我们还要减去$GCD$为$2$的矩形的数量。

也就是说答案是:$\sum \limits_{i=1}^{n-1}\sum \limits_{j=1}^{m-1}[gcd(i,j)=1]((n-i)(m-j)-\max(n-2\times i,0)\times \max(m-2\times j,0))$

$60\%$算法:

每次暴力求上面那个式子。

时间复杂度:$\Theta(T\times n\times m)$。

期望得分:$60$分。

实际得分:$60$分。

$100\%$算法$1$:

通过前缀和预处理出来答案,然后$\Theta(1)$查询即可。

时间复杂度:$\Theta(T+4000\times 4000)$。

期望得分:$100$分。

实际得分:$100$分。

$100\%$算法$2$:

我也不太会,大概讲两句:

化简?上面那个式子:

$\sum \limits_{i=1}^{n-1}\sum \limits_{j=1}^{m-1}[gcd(i,j)=1]((n-i)(m-j)-\max(n-2\times i,0)\times \max(m-2\times j,0)) \\ =\sum \limits_{i=1}^{n-1}\sum \limits_{j=1}^{m-1}\sum \limits_{d|gcd(i,j)}\mu (d)\times ((n-i)(m-j)-\max(n-2\times i,0)\times \max(m-2\times j,0)) \\ =\sum \limits_{d=1}{n-1}\mu (d)\times \sum \limits_{i=1}^{\left \lfloor \dfrac{n-1}{d} \right \rfloor}\sum \limits_{j=1}^{\left \lfloor \dfrac{m-1}{d} \right \rfloor}\sum \limits_{x=1}^{n-i\times d}\sum \limits_{y=1}^{m-j\times d}[x\leqslant i\times d\ or\ y\leqslant j\times d] \\ =\sum \limits_{d=1}^{n-1}\mu (d)\times \sum \limits_{i=1}^{\left \lfloor \dfrac{n-1}{d} \right \rfloor}\sum \limits_{j=1}^{\left \lfloor \dfrac{m-1}{d} \right \rfloor}(\sum \limits_{x=1}^{n-i\times d}[x\leqslant i\times d]\times (m-j\times d)) \\ +(\sum \limits_{y=1}^{m-j\times d}[y\leqslant j\times d]\times (n-i\times d)) \\ -(\sum \limits_{x=1}^{n-i\times d}\sum \limits_{y=1}^{m-i\times d}[x\leqslant i\times d\ and\ y\leqslant j\times d]) \\ =\sum \limits_{d=1}^{n-1}\mu (d)\times (\sum \limits_{i=1}^{\left \lfloor \dfrac{n-1}{d}\right \rfloor}\sum \limits_{x=1}^{n-i\times d}[x\leqslant i\times d]\times \sum \limits_{j=1}^{\left \lfloor \dfrac{m-1}{d}\right \rfloor}(m-j\times d)) \\ +(\sum \limits_{j=1}^{\left \lfloor \dfrac{m-1}{d} \right \rfloor}\sum \limits_{y=1}^{m-j\times d}[y\leqslant j\times d]\times \sum \limits_{i=1}^{\left \lfloor \dfrac{n-1}{d}\right \rfloor}(n-i\times d)) \\ -\sum \limits_{i=1}^{\left \lfloor \dfrac{n-1}{d}\right \rfloor}\sum \limits_{x=1}^{n-i\times d}[x\leqslant i\times d]\times \sum \limits_{j=1}^{\left \lfloor \dfrac{m-1}{d}\right \rfloor}\sum \limits_{y=1}^{m-j\times d}[y\leqslant j\times d])$

希望我上面那么长的$\LaTeX$没有打错吧,毕竟它……

时间复杂度:$\Theta(T\times n)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

$60\%$算法:

#include<bits/stdc++.h>
using namespace std;
int n,m;
unsigned int ans;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
ans=0;
for(int i=1;i<n;i++)
for(int j=1;j<m;j++)
if(__gcd(i,j)==1)
ans+=(n-i)*(m-j)-(max((n-(i<<1)),0)*max(m-(j<<1),0));
printf("%d\n",(n+m+(ans<<1))&1073741823);
}
return 0;
}

$100\%$算法$1$:

#include<bits/stdc++.h>
using namespace std;
int n,m;
pair<unsigned int,unsigned int> s[4001][4001];
int main()
{
for(int i=1;i<=4000;i++)
for(int j=1;j<=4000;j++)
{
s[i][j].first=(s[i-1][j].first+s[i][j-1].first-s[i-1][j-1].first+(__gcd(i,j)==1))&1073741823;
s[i][j].second=(s[i-1][j].second+s[i][j-1].second-s[i-1][j-1].second+s[i][j].first-s[i>>1][j>>1].first)&1073741823;
}
int T;scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
printf("%d\n",(n+m+(s[n-1][m-1].second<<1))&1073741823);
}
return 0;
}

$100\%$算法$2$:

#include<bits/stdc++.h>
using namespace std;
int n,m;
int phi[4001],mu[4001];
bool vis[4001];
unsigned int ans;
void pre_work()
{
mu[1]=1;
for(int i=2;i<=4000;i++)
{
if(!vis[i]){phi[++phi[0]]=i;mu[i]=-1;}
for(int j=1;j<=phi[0];j++)
{
if(i*phi[j]>4000)break;
vis[i*phi[j]]=1;
if(!(i%phi[j])){mu[i*phi[j]]=0;break;}
mu[i*phi[j]]=-mu[i];
}
}
}
int main()
{
pre_work();
int T;scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
ans=0;
for(int i=1;i<n;i++)
ans+=2*mu[i]*(((n/(2*i)+1)*(n/(2*i))*i/2+n*((n-1)/i-n/(2*i))-((n-1)/i+n/(2*i)+1)*((n-1)/i-n/(2*i))*i/2)*(m*((m-1)/i)-((m-1)/i)*((m-1)/i+1)*i/2)+((m/(i*2)+1)*(m/(i*2))*i/2+m*((m-1)/i-m/(i*2))-((m-1)/i+m/(i*2)+1)*((m-1)/i-m/(i*2))*i/2)*(n*((n-1)/i)-((n-1)/i)*((n-1)/i+1)*i/2)-((n/(2*i)+1)*(n/(2*i))*i/2+n*((n-1)/i-n/(2*i))-((n-1)/i+n/(2*i)+1)*((n-1)/i-n/(2*i))*i/2)*((m/(i*2)+1)*(m/(i*2))*i/2+m*((m-1)/i-m/(i*2))-((m-1)/i+m/(i*2)+1)*((m-1)/i-m/(i*2))*i/2));
printf("%d\n",(n+m+ans)&1073741823);
}
return 0;
}

rp++

[CSP-S模拟测试]:夜鹰与玫瑰(数学)的更多相关文章

  1. [CSP-S模拟测试]:题(DP+数学)

    题目描述 出个题就好了.这就是出题人没有写题目背景的原因.你在平面直角坐标系上.你一开始位于$(0,0)$.每次可以在上/下/左/右四个方向中选一个走一步.即:从$(x,y)$走到$(x,y+1),( ...

  2. [CSP-S模拟测试]:C(倍增+数学)

    题目传送门(内部题152) 输入格式 第一行两个整数$N,Q$. 接下来一行$N$个整数,第$i$个为$a_i$. 接下来的$N-1$行,每行两个整数$u,v$.表示$u,v$之间有一条边. 接下来的 ...

  3. [CSP-S模拟测试]:B(DP+数学)

    题目传送门(内部题45) 输入格式 第一行$3$个整数$n,m,P$.第二行$m$个整数,表示$m$次询问. 输出格式 一行$m$个整数表示答案. 样例 样例输入1: 2 4 40 1 2 3 样例输 ...

  4. [CSP-S模拟测试]:物理课(数学)

    题目传送门(内部题144) 输入格式 从$physics.in$读入数据. 第一行一个数$T$,代表有$T$组数据.接下来$T$行每行$4$个浮点数,分别为$\theta,v,d,g$,保留到小数点后 ...

  5. [CSP-S模拟测试]:最大或(数学)

    题目传送门(内部题141) 输入格式 输入文件包含多组测试数据,第一行为一个正整数$T$,表示数据组数. 接下来$T$行,每行两个正整数$l,r$.数据保证$l\leqslant r$成立. 输出格式 ...

  6. [CSP-S模拟测试]:平方数(数学+哈希)

    题目传送门(内部题137) 输入格式 第一行,一个正整数$n$. 第二行$n$个正整数$a_1\sim a_n$. 输出格式 输出一个整数,为满足条件的二元组个数. 样例 样例输入: 51 2 3 4 ...

  7. [CSP-S模拟测试]:简单计算(数学)

    题目传送门(内部题104) 输入格式 第一行一个正整数$T$,表示该测试点内的数据组数,你需要对该测试点内的$T$组数据都分别给出正确的答案才能获得该测试点的分数. 接下来$T$组数据,每组数据一行两 ...

  8. [CSP-S模拟测试]:异或(数学)

    题目描述 给定$L,R$,我们希望你求出:$$\sum\limits_{i=L}^R\sum\limits_{j=L}^R(i\oplus j)$$其中这里的$\oplus$表示异或运算.答案对$10 ...

  9. [CSP-S模拟测试]:位运算(数学)

    题目传送门(内部题72) 输入格式 输入文件$bit.in$ 每个输入文件包含$T$组测试数据.输入文件的第一行为一个整数$T$,表示数据组数.接下来$T$行,每行表示一组测试数据每组测试数据包括三个 ...

随机推荐

  1. Pasha and Tea

    Pasha and Tea time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  2. eclipse项目(java project)如何导入jar包的解决方案列表?

    右键项目-properties-java build path(左侧菜单)-选择libraries 有两种方式,导入jar包实际上就是建立一种链接,并不是copy式的导入 一.导入外部包,add ex ...

  3. Mac上VMWare Fusion配置多台cent os

    一.创建虚拟机(准备工作) 1.使用VMWare Fusion 创建第一台虚拟机 2.选择操作系统(本次使用的是使用cent os 6.5 64bit 系统) 3.选择磁盘大小(楼主mac上的磁盘大小 ...

  4. spark sql correlated scalar subqueries must be aggregated 错误解决

    最近在客户中使用spark sql 做一些表报处理,但是在做数据关联时,老是遇到 “correlated scalar subqueries must be aggregated” 错误 举一个例子, ...

  5. centos7下zookeeper安装配置

    1.下载zookeeper文件 cd /opt/ wget http://mirrors.hust.edu.cn/apache/zookeeper/stable/zookeeper-3.4.9.tar ...

  6. Bootstrap 学习笔记2 栅格系统 辅助类下拉框

    辅助类和响应式工具: 颜色和字体相同 响应式工具: 图标菜单按钮组件: btn-group 按钮式下拉菜单

  7. js中的attributes和Attribute的用法和区别。

    一:Attribute的几种用法和含义(attributes和Attribute都是用来操作属性的) getAttribute:获取某一个属性的值: setAttribute:建立一个属性,并同时给属 ...

  8. 使用UI Automation实现自动化测试--5-7

    使用UI Automation实现自动化测试--5 (Winfrom和WPF中弹出和关闭对话框的不同处理方式) 在使用UI Automation对Winform和WPF的程序测试中发现有一些不同的地方 ...

  9. UVA1629_Cake slicing

    Cake slicing 给你一个矩形大小,和每个樱桃的坐标,现在让你去切使得切之后的小矩形包含一个樱桃,每次切的代价是切痕的长度,问你最小代价是多少 思路: 首先要明白一点,不能切除一个不含樱桃的矩 ...

  10. 五、hibernate表与表之间的关系(一对多关系)

    数据库表与表之间的关系 一对多:一个学校可以有多个学生,一个学生只能有一个学校 多对多:一个学生可以有多个老师,一个老师可以教多个学生 一对一:一个人只能有一个身份证号,一个身份证号只能找到一个人 一 ...