[CSP-S模拟测试]:夜鹰与玫瑰(数学)
题目描述
红晕爬上了白玫瑰的花瓣,花刺还没有到达夜莺的心脏,玫瑰的心依旧苍白如终年不化的积雪。由生命铸就的玫瑰不允许存在一丝一毫的瑕疵,假设玫瑰的一片花瓣可以抽象成一个点,一朵玫瑰我们用一个$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模拟测试]:夜鹰与玫瑰(数学)的更多相关文章
- [CSP-S模拟测试]:题(DP+数学)
题目描述 出个题就好了.这就是出题人没有写题目背景的原因.你在平面直角坐标系上.你一开始位于$(0,0)$.每次可以在上/下/左/右四个方向中选一个走一步.即:从$(x,y)$走到$(x,y+1),( ...
- [CSP-S模拟测试]:C(倍增+数学)
题目传送门(内部题152) 输入格式 第一行两个整数$N,Q$. 接下来一行$N$个整数,第$i$个为$a_i$. 接下来的$N-1$行,每行两个整数$u,v$.表示$u,v$之间有一条边. 接下来的 ...
- [CSP-S模拟测试]:B(DP+数学)
题目传送门(内部题45) 输入格式 第一行$3$个整数$n,m,P$.第二行$m$个整数,表示$m$次询问. 输出格式 一行$m$个整数表示答案. 样例 样例输入1: 2 4 40 1 2 3 样例输 ...
- [CSP-S模拟测试]:物理课(数学)
题目传送门(内部题144) 输入格式 从$physics.in$读入数据. 第一行一个数$T$,代表有$T$组数据.接下来$T$行每行$4$个浮点数,分别为$\theta,v,d,g$,保留到小数点后 ...
- [CSP-S模拟测试]:最大或(数学)
题目传送门(内部题141) 输入格式 输入文件包含多组测试数据,第一行为一个正整数$T$,表示数据组数. 接下来$T$行,每行两个正整数$l,r$.数据保证$l\leqslant r$成立. 输出格式 ...
- [CSP-S模拟测试]:平方数(数学+哈希)
题目传送门(内部题137) 输入格式 第一行,一个正整数$n$. 第二行$n$个正整数$a_1\sim a_n$. 输出格式 输出一个整数,为满足条件的二元组个数. 样例 样例输入: 51 2 3 4 ...
- [CSP-S模拟测试]:简单计算(数学)
题目传送门(内部题104) 输入格式 第一行一个正整数$T$,表示该测试点内的数据组数,你需要对该测试点内的$T$组数据都分别给出正确的答案才能获得该测试点的分数. 接下来$T$组数据,每组数据一行两 ...
- [CSP-S模拟测试]:异或(数学)
题目描述 给定$L,R$,我们希望你求出:$$\sum\limits_{i=L}^R\sum\limits_{j=L}^R(i\oplus j)$$其中这里的$\oplus$表示异或运算.答案对$10 ...
- [CSP-S模拟测试]:位运算(数学)
题目传送门(内部题72) 输入格式 输入文件$bit.in$ 每个输入文件包含$T$组测试数据.输入文件的第一行为一个整数$T$,表示数据组数.接下来$T$行,每行表示一组测试数据每组测试数据包括三个 ...
随机推荐
- socket | netcat 模拟
#!/opt/local/bin/python2.7 #coding=utf-8 ''' 取代netcat 两台主机中其中一台控制另一台 得到北控方的shell ''' import sys impo ...
- Windows10下安装CentOS7双系统
参考: 参考1 参考2 问题1
- drf:restful概念,类继承关系,drf请求封装,drf请求流程,版本控制组件,认证组件(token),权限组件
1.restful规范 resfful规范的概念最重要: 是一套规范,规则,用于程序之间进行数据交换的约定. 他规定了一些协议,对我们感受最直接的就是,以前写增删改查的时候需要些四个视图寒素,rest ...
- 指针的value
全局变量的默认初始化值为0,char为空字符——'\0',string为"\0 " char c; string s; ; int main() { cout << p ...
- spring boot 尚桂谷学习笔记08 Docker ---Web
------Docker------ 简介:Docker是一个开元的应用容器引擎,性能非常高 已经安装好的软件打包成一个镜像放到服务器中运行镜像 MySQL容器,Redis容器...... Docke ...
- Git 内部原理
首先要弄明白一点,从根本上来讲 Git 是一个内容寻址(content-addressable)文件系统,并在此之上提供了一个版本控制系统的用户界面. 马上你就会学到这意味着什么. git objec ...
- upc组队赛14 As rich as Crassus【扩展中国剩余定理】
As rich as Crassus 题目链接 题目描述 Crassus, the richest man in the world, invested some of his money with ...
- 微信小程序发送红包功能。填坑记录
微信官方文档 1.开通条件 (1)商户号已入驻90日 (2)商户号有连续30天正常交易 (3)只有企业资质的商户才有资格申请 2.注意事项 (1)目前小程序红包仅支持用户微信扫码打开小程序 (2)小程 ...
- 洛谷 P1346 电车——dijstra
上一波题目 https://www.luogu.org/problem/P1346 是道水题 路口一开始对着的那条路权值为0 其余路权值为1 然后跑一遍最短路就好了 qwq #include<c ...
- python基础----找零问题
给定要找回的总钱数和硬币的种类,求出找零所需最少的硬币数目. 例如: 总钱数63,硬币种类为25.21.10.5.1,求出最小硬币数 分析: 我们可以先假设只有一种硬币1, 假如总钱数为1,硬币数就为 ...