1844 Sum 添加适当的+,-使得(1,n)和等于S

Sum
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 7765 Accepted: 4999

Description

Consider the natural numbers from 1 to N. By associating to each number a sign (+ or -) and calculating the value of this expression we obtain a sum S. The problem is to determine for a given sum S the minimum number N for which we can obtain S by associating signs for all numbers between 1 to N.

For a given S, find out the minimum value N in order to obtain S according to the conditions of the problem.

Input

The only line contains in the first line a positive integer S (0< S <= 100000) which represents the sum to be obtained.

Output

The output will contain the minimum number N for which the sum S can be obtained.

Sample Input

12

Sample Output

7

Hint

The sum 12 can be obtained from at least 7 terms in the following way: 12 = -1+2+3+4+5+6-7.
我也是看了各位大牛的讨论才明白的, 我把它写的更加具体点了而已
一:sum一定要大于或等于输入的S.(等于时就已经找到了答案)
   小于的话就算全做加法运算也不能达到S。
            
二:在满足第一条的情况下,注意一定要满足第一条后
   第一次碰到(sum - S ) % 2 == 0
 这里( sum = 1 + 2  + .... + i )这时的i就是答案。
  证明如下:
             1:若res是奇数,就说明res = ( 1 + 2 + ... + i )- S 是奇数
             也就是说无论你怎么改变sum( sum = 1 + 2  + .... + i )的表达式
             (当然是通过改变其中的加号为减号)
             举个例子吧:S = 5, sum = 1+2+3 = 6, res = 6 - 5 = 1;
           无论改变(1+2+3)中的加号也没用,这是因为你在sum中改变一个加号为减号
             时它的值就一定减少了一个偶数值(这是显然的)。
             2:令res = sum - S,则res一定是0,2, 4, 6....中的一个
             当k = 0的情况就不用说明了吧, 假设2k表示res 显然k = 1 2 3 4...
            当k = 1 时可以通过把sum( sum = 1 + 2 + ... + i )
            改成( sum = -1 + 2 + ... + i )
            当k = 2 时可以通过把sum ( sum = 1 + 2 + ... + i )
            改成( sum = 1 - 2 + ... + i )
         
其实这个题还有一种理解思路就是怎么添加最少的减号使得1, 2, 3, 4,... i的和是S。 
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
    int s;
    while(scanf("%d",&s)==1)
    {
        int sum=0,i;
        for(i=1;;i++)
        {
            sum+=i;
            if(sum==s) break;
            if(sum>s&&(sum-s)%2==0) break;
        }
        printf("%d/n",i);
    }
    return 0;
}
(在您提供的代码中,dbscanParallel函数中包含了一个注释掉的部分,这部分代码是用来输出噪声点(即被标记为-1的点)的。当这部分代码被注释掉时,程序不会输出任何噪声点信息。 从您提供的截图来看,当代码运行时,如果包含输出噪声点的代码被注释掉,那么并行串行的输出结果会有所不同,因为串行版本中噪声点的检测标记是同步进行的,而并行版本中这部分工作被多个线程并发执行。这可能导致并行版本的噪声点检测结果与串行版本不一致。 此外,由于并行执行时多个线程同时访问修改共享数据(如labels数组),如果没有适当的同步机制(如原子操作或互斥锁),可能会导致数据竞争不一致的结果。)根据以上描述改进代码:#include <fstream> #include <iostream> #include <vector> #include <cmath> #include <sstream> #include <string> #include <unordered_set> #include <chrono> #include <algorithm> #include <omp.h> #include <atomic> #include <mutex> struct Point { std::vector<double> values; }; double euclideanDistance(const Point& p1, const Point& p2) { double sum = 0.0; for (size_t i = 0; i < p1.values.size(); ++i) { sum += (p1.values[i] - p2.values[i]) * (p1.values[i] - p2.values[i]); } return std::sqrt(sum); } void dbscanParallel(const std::vector<Point>& points, double eps, int minPts, std::vector<int>& labels) { std::atomic<int> label(0); std::vector<std::atomic<bool>> visited(points.size()); for (auto& v : visited) v.store(false, std::memory_order_relaxed); std::vector<int> noise; #pragma omp parallel { std::vector<int> local_noise; #pragma omp for schedule(dynamic) for (int i = 0; i < points.size(); ++i) { bool expected = false; if (visited[i].compare_exchange_strong(expected, true)) { std::unordered_set<int> neighbors; // 串行计算邻居 for (int j = 0; j < points.size(); ++j) { if (i != j && euclideanDistance(points[i], points[j]) <= eps) { neighbors.insert(j); } } if (neighbors.size() < minPts) { labels[i] = -1; local_noise.push_back(i); } else { int current_label = label.fetch_add(1, std::memory_order_relaxed); labels[i] = current_label; std::vector<int> seeds(neighbors.begin(), neighbors.end()); for (size_t k = 0; k < seeds.size(); ++k) { int seed = seeds[k]; bool seed_expected = false; if (visited[seed].compare_exchange_strong(seed_expected, true)) { labels[seed] = current_label; // 扩展新邻居 std::unordered_set<int> new_neighbors; for (int j = 0; j < points.size(); ++j) { if (j != seed && !visited[j].load(std::memory_order_relaxed) && euclideanDistance(points[seed], points[j]) <= eps) { new_neighbors.insert(j); } } if (new_neighbors.size() >= minPts) { seeds.insert(seeds.end(), new_neighbors.begin(), new_neighbors.end()); } } } } } } #pragma omp critical noise.insert(noise.end(), local_noise.begin(), local_noise.end()); } /*if (!noise.empty()) { std::cout << "Noise points:" << std::endl; for (int idx : noise) { std::cout << "Point " << idx << ": "; for (double val : points[idx].values) { std::cout << val << " "; } std::cout << std::endl; } } else { std::cout << "No noise points detected." << std::endl; }*/ } // 其他函数(如readCSV、dbscanSerial)保持不变 std::vector<Point> readCSV(const std::string& filename) { std::vector<Point> points; std::ifstream file(filename); std::string line; while (std::getline(file, line)) { std::istringstream iss(line); std::string token; Point point; while (std::getline(iss, token, ',')) { point.values.push_back(std::stod(token)); } points.push_back(point); } return points; } void dbscanSerial(const std::vector<Point>& points, double eps, int minPts, std::vector<int>& labels) { int label = 0; std::vector<bool> visited(points.size(), false); std::vector<int> noise; for (int i = 0; i < points.size(); ++i) { if (!visited[i]) { std::unordered_set<int> neighbors; for (int j = 0; j < points.size(); ++j) { if (i != j && euclideanDistance(points[i], points[j]) <= eps) { neighbors.insert(j); } } if (neighbors.size() < minPts) { labels[i] = -1; // Mark as noise noise.push_back(i); } else { label = ++label; std::unordered_set<int> seeds = neighbors; while (!seeds.empty()) { int seed = *seeds.begin(); seeds.erase(seeds.begin()); visited[seed] = true; labels[seed] = label; std::unordered_set<int> new_neighbors; for (int j = 0; j < points.size(); ++j) { if (!visited[j] && euclideanDistance(points[seed], points[j]) <= eps) { new_neighbors.insert(j); } } for (int j : new_neighbors) { if (neighbors.find(j) == neighbors.end()) { seeds.insert(j); neighbors.insert(j); } } } for (auto it = neighbors.begin(); it != neighbors.end(); ++it) { visited[*it] = true; labels[*it] = label; } } } } /*if (!noise.empty()) { std::cout << "Noise points:" << std::endl; for (int idx : noise) { std::cout << "Point " << idx << ": "; for (double val : points[idx].values) { std::cout << val << " "; } std::cout << std::endl; } } else { std::cout << "No noise points detected." << std::endl; }*/ } int main(int argc, char** argv) { int num_threads = 4; // Default number of threads if (argc > 1) { num_threads = std::stoi(argv[1]); } omp_set_num_threads(num_threads); auto points = readCSV("D:\\桌面\\并行程序\\naiveBayes\\naiveBayes\\iris.csv"); double eps = 0.5; // Epsilon value int minPts = 5; // Minimum points to form a dense region std::vector<int> labels(points.size(), 0); // Serial DBSCAN auto startSerial = std::chrono::high_resolution_clock::now(); dbscanSerial(points, eps, minPts, labels); auto endSerial = std::chrono::high_resolution_clock::now(); std::chrono::duration<double> elapsedSerial = endSerial - startSerial; // Parallel DBSCAN std::fill(labels.begin(), labels.end(), 0); auto startParallel = std::chrono::high_resolution_clock::now(); dbscanParallel(points, eps, minPts, labels); auto endParallel = std::chrono::high_resolution_clock::now(); std::chrono::duration<double> elapsedParallel = endParallel - startParallel; // Calculate speedup and efficiency double speedup = elapsedSerial.count() / elapsedParallel.count(); double efficiency = (speedup / num_threads) * 100; // Print performance results std::cout << "\nPerformance Results:" << std::endl; std::cout << "+------------+----------------+------------------+--------------+----------------+" << std::endl; std::cout << "| Threads | Serial Time (s)| Parallel Time (s)| Speedup | Efficiency (%) |" << std::endl; std::cout << "+------------+----------------+------------------+--------------+----------------+" << std::endl; printf("| %-10d | %-14.6f | %-16.6f | %-12.6f | %-14.2f |\n", num_threads, elapsedSerial.count(), elapsedParallel.count(), speedup, efficiency); std::cout << "+------------+----------------+------------------+--------------+----------------+" << std::endl; return 0; }
05-11
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值