#include <iostream> #include <map> #include <vector> #include <unordered_map> #define int long long using namespace std; const int mod = 1e9 + 7; signed main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int t; cin >> t; while(t --) { int ans = 0; int n; cin >> n; if(n % 2) { int k = n; int tmp = n / 2; int cnt = 0; while(cnt < tmp) { cnt ++; ans = (ans + ((k * 1) % mod)) % mod; } } else { int k = n; int tmp = n / 2; int cnt = 0; while(cnt < tmp) { cnt ++; ans = (ans + ((k * 1) % mod)) % mod; } } cout << ans << '\n'; } }优化一下时间复杂度
时间: 2025-06-12 12:10:54 浏览: 17
<think>嗯,我现在得看看用户提供的这段C++代码,然后想办法优化它的时间复杂度。首先,我需要理解这段代码在做什么。让我仔细看一下。
代码的大致结构是,输入t个测试用例,每个用例输入一个n,然后根据n是奇数还是偶数来计算ans的值。最后输出ans。看起来无论n是奇数还是偶数,代码的结构其实差不多,都是计算n的一半的次数,然后把k(也就是n)累加到ans中,每次取模。
比如,当n是奇数的时候,n/2会得到一个整数部分,比如n=5的话,tmp就是2,循环两次,每次加上5。那结果就是5+5=10。如果是n=6,tmp是3,循环三次,每次加6,结果是18。对吧?
但是不管n是奇数还是偶数,代码里的处理方式其实是一样的,只是tmp的值是n/2,然后循环tmp次,每次加上n。所以无论奇偶,实际上都是执行n/2次加法,每次加n。不过当n是奇数时,n/2是向下取整,所以比如n=5的话,tmp=2,循环两次,得到5*2=10。而如果是n=7,tmp=3,循环三次,得到7*3=21。哦,等一下,当n是奇数的时候,n/2其实是(n-1)/2,对吗?比如7/2=3.5,但整数除法会得到3。所以循环次数是3次。所以总的结果是n乘以(n//2),然后对mod取模。
那这样的话,这个循环其实可以简化为一个乘法,而不是循环累加。比如,ans = (n * (n//2)) % mod。这样时间复杂度就从O(n/2)降到了O(1),因为原来的循环次数是和n成线性关系,现在只需要一步计算。
那原来的代码无论n是奇数还是偶数,都执行n//2次循环,每次加n。那么总和应该是n * (n//2)。例如,当n=6时,6//2=3,6*3=18。原来的代码确实是这样计算的。当n=5时,5//2=2,5*2=10。所以不管n的奇偶性,ans的计算结果都是n乘以(n除以2的整数部分)。
那么优化方法就是把循环替换为直接计算n*(n//2) % mod。这样时间复杂度就从O(t * n)变成O(t),因为每个测试用例的处理时间都是常数时间,而原来的时间复杂度对于每个测试用例来说是线性的,即O(n)。当n很大时,比如1e9,原来的循环会超时,而优化后的方法不会有这个问题。
那现在需要检查原代码中的条件判断是否有必要。因为当n是奇数或偶数时,代码的处理逻辑其实是一样的,都是执行n//2次循环。所以可以去掉if-else条件判断,统一处理。例如,不管n是奇数还是偶数,tmp = n//2,然后ans = (n * tmp) % mod。这样就可以简化代码,同时减少条件判断的开销。
那么原来的代码中的if-else分支实际上可以合并,因为它们执行相同的操作。所以可以删掉条件判断,直接计算tmp = n / 2(注意这里的除法是整数除法),然后ans = (n * tmp) % mod。
那修改后的代码应该更高效,时间复杂度降到了O(1)每个测试用例。原来的代码在t很大的情况下,比如t=1e5,每个n=1e9,原来的循环会超时,而优化后的代码可以轻松处理。
另外,原来的代码可能还有一些可以优化的地方,比如变量k被赋值为n,但实际上k没有被改变过,所以在循环里每次都是加n。所以直接使用n即可,不需要用k。这可能只是原代码作者的冗余写法。
总结一下,优化步骤是:
1. 去除条件判断,统一处理奇偶情况。
2. 将循环累加改为直接计算乘积并取模。
这样时间复杂度从O(t * n)优化到O(t),每个测试用例只需常数时间。</think>该代码的时间复杂度可以从$O(n)$优化到$O(1)$。以下是分步说明和优化后的代码:
---
### **原代码分析**
```cpp
if(n % 2) {
int k = n;
int tmp = n / 2; // 例如n=5时,tmp=2
// 循环tmp次,每次加k(即n)
} else {
int k = n;
int tmp = n / 2; // 例如n=6时,tmp=3
// 循环tmp次,每次加k(即n)
}
```
无论奇偶,实际计算的是:
$$ ans = n \times \left\lfloor \frac{n}{2} \right\rfloor \mod (10^9+7) $$
---
### **优化步骤**
1. **数学推导**
循环累加$n$共$\left\lfloor \frac{n}{2} \right\rfloor$次,等价于直接计算:
$$
ans = \left( n \times \left\lfloor \frac{n}{2} \right\rfloor \right) \mod (10^9+7)
$$
将$O(n)$的循环简化为$O(1)$的乘法。
2. **移除冗余条件判断**
奇偶分支实际执行相同操作,合并代码逻辑。
---
### **优化后代码**
```cpp
#include <iostream>
#define int long long
using namespace std;
const int mod = 1e9 + 7;
signed main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int t;
cin >> t;
while(t--) {
int n;
cin >> n;
int tmp = n / 2; // 自动向下取整
int ans = (n % mod) * (tmp % mod) % mod; // 防溢出写法
cout << ans << '\n';
}
}
```
---
### **关键优化点**
1. **时间复杂度**
从$O(t \cdot n)$优化到$O(t)$,每个测试用例只需常数时间。
2. **防溢出处理**
使用`(a % mod) * (b % mod) % mod`确保乘法不溢出。
3. **代码简化**
移除冗余变量`k`和循环结构,逻辑更清晰。
---
### **验证示例**
- **输入n=5**
$5/2=2$, 结果$5 \times 2 = 10 \mod (10^9+7)$
- **输入n=6**
$6/2=3$, 结果$6 \times 3 = 18 \mod (10^9+7)$
优化后代码在功能上与原代码完全一致,但效率显著提升。
阅读全文
相关推荐










