我正在解决CS问题,我需要的帮助不大。我有数字N,如果矩形被分割成大小为1x1的矩形,我需要计算对角线在N个方格中经过的不同矩形的数量。这张照片将帮助您理解。
如果N = 4,这张图片显示所有4种组合,实际上对角线在4个方格中经过的矩形的大小为1x4,2x3,4x2和4x4。
如果我们给出了两个尺寸的矩形,我找到了公式:
A + B - gcd(A,B)
由于N <= 10 ^ 6,i上升到10 ^ 6并检查N的除数为N,其复杂度为O(N sqrt(N)),因为A的除数是gcd(A,B)我解决了方程组 q是A的除数,q是gcd(A,B) A + B-q = N且gcd(A,B)= q 我在O(N sqrt(N)* log(N))中解决了这个问题 其中我假设log(N)是找到两个数字的gcd的时间。
因为时间限制是3秒,所以它会按时失败。我需要有关优化解决方案的帮助。
更新:这是我的代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int a;
int gcd(int a, int b) {
if(b>a) swap(a,b);
if(b==0) return a;
return gcd(b, a%b);
}
bool valid(int n, int m, int gc, int a) {
if(n+m-gc==a) return true;
return false;
}
int main() {
cin>>a;
int counter=0;
for(int i=1;i<=a/2;i++) {
for(ll j=1;j<=sqrt(i);j++) {
if(i%j==0) {
if(j!=i/j) {
int m1 = a+j-i;
int div=i/j;
int m2 = a+div-i;
if(valid(i, m1, j, a)) {
if(gcd(i, m1)==j)
counter++;
}
if(valid(i, m2, i/j, a)) {
if(gcd(i,m2)==i/j)
counter++;
}
}
else {
int m1 = a+j-i;
if(valid(i, m1, j, a)) {
if(gcd(i, m1)==j)
counter++;
}
}
}
}
}
cout<<counter+1;
return 0;
}
提前致谢。
答案 0 :(得分:1)
虽然O(n*sqrt(n)*log(n))
n <= 10^6
听起来有点多,但您可能需要更好的算法,但您的代码支持一些优化:
int gcd(int a, int b) {
if(b>a) swap(a,b);
if(b==0) return a;
return gcd(b, a%b);
}
摆脱交换,没有它就可以正常工作。
当你在这里时,也要摆脱递归:
int gcd(int a, int b) {
while (b) {
int r = a % b;
a = b;
b = r;
}
return a;
}
下一步:
for(int i=1;i<=a/2;i++) {
for(ll j=1;j<=sqrt(i);j++) {
在各自的循环之外计算a/2
和sqrt(i)
。没有必要在每次迭代时计算它。编译器可能或者可能不够智能(或设置)来做到这一点,但你不应该依赖它,特别是在在线判断设置中。
您还可以进一步预先计算i / j
,以便不会每次都重新计算它。许多分歧可能很慢。
接下来,long long
你真的需要j
吗? i
是一个int,j
上升到平方根。因此long long
不需要j
,请使用int
。