zoukankan      html  css  js  c++  java
  • hdu 2058:The sum problem

    题意

    序列1,2,...n,求出所有子串,使得和为m

    类型

    数学

    思路

    由求和公式易得
    b(b+1)/2 - a(a+1)/2 = m  ( 0 <= a < b <= n )
    配方得
    (b+1/2)^2 - (a-1/2)^2 = m
    然后
    (b-a)(a+b+1) = 2m
    这样出现了两个数相乘得2m
    这些数必然是2m的质因子相乘
    状态枚举,然后去重去不合法,然后排序,就OK
    (其实,a+b+1 < sqrt(2m) 所以枚举就可以了)

    收获

    一种解二元二次不定方程的思路(配方,平方差公式,质因子枚举)

    代码

    /*************************************************************************
        > File Name:    hd2058.cpp
        > Author:       Shine
        > Created Time: 2013-06-27 下午 6:16:55
        > QuestionType: 数学
        > Way: (b-a)(a+b+1) == 2m (其实暴力枚举a+b+1的值就可以了(到根号2m))
        > Submit: 3WA 1AC
        > Gain: 尝试了一下状态枚举和分解质因子的写法
        > Experience: 对于每一步,想想,有必要吗?暴力可以吗?
     ************************************************************************/
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define N 100050
    int prime[N];
    int p = 0;
    
    int getprime() {
        int i, j;
        for (i = 2; i < N; i++) {
            for (j = 2; j * j < i; j++) {
                if (i % j == 0) break;
            }
            if (j * j >= i) prime[p++] = i;
        }
        return p;
    }
    
    int primInM[100];
    struct RE {
        int a, b;
        bool operator < (const RE &c) const { 
            if (a != c.a) return a < c.a;
            else return b < c.b;
        }
    }re[10000];
    
    int main() {
        getprime();
        int n, m;
        while (~scanf("%d%d", &n, &m) && n && m) {
            int dm = 2*m;
            int i;
            int mp = 0;
            //分解质因子
            for (i = 0; i < p && dm > 1; i++) {
                while (dm % prime[i] == 0) {
                    dm /= prime[i];
                    primInM[mp++] = prime[i];
                }
            }
            if (dm > 1) primInM[mp++] = dm;
            dm = 2*m;
    
            int rep = 0;
            int endstate = 1<<mp;
            int state = 0;
            while(state < endstate) {
                int A = 1, B = 1;
                for (i = 0; i < mp; i++) {
                    if (state & (1<<i)) A *= primInM[i];
                }
                B = dm / A;
                int a = (B-A-1)/2;
                int b = (A+B-1)/2;
                if (!(a < 0 || b <= 0 || a >= b) && (b-a)*(a+b+1) == dm && b <= n && a <= n) {
                    re[rep].a = a;
                    re[rep].b = b;
                    rep++;
                }
                state++;
            }
    
            sort(re, re+rep);
    
            int prea = -1, preb = -1;
            for (i = 0; i < rep; i++) {
                if (re[i].a == prea && re[i].b == preb) continue;
                prea = re[i].a; preb = re[i].b;
                printf("[%d,%d]
    ", re[i].a+1, re[i].b);
            }puts("");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Word添加论文引用标注
    从入门示例看ns2脚本的基本结构
    Linux下Socket编程
    c++中的枚举类型
    运算符重载的规则
    标志位处理
    mfc中从类名获取类运行时信息
    用自定义类声明全局变量的一种快捷方式
    基类的析构函数声明为virtual比较安全
    VC常用数据类型使用转换详解(摘)
  • 原文地址:https://www.cnblogs.com/shinecheng/p/3159779.html
Copyright © 2011-2022 走看看