《算法竞赛进阶指南》0.8总结与练习(1)

116. 飞行员兄弟

“飞行员兄弟”这个游戏,需要玩家顺利的打开一个拥有16个把手的冰箱。

已知每个把手可以处于以下两种状态之一:打开或关闭。

只有当所有把手都打开时,冰箱才会打开。

把手可以表示为一个4х4的矩阵,您可以改变任何一个位置[i,j]上把手的状态。

但是,这也会使得第i行和第j列上的所有把手的状态也随着改变。

请你求出打开冰箱所需的切换把手的次数最小值是多少。

输入格式
输入一共包含四行,每行包含四个把手的初始状态。
符号“+”表示把手处于闭合状态,而符号“-”表示把手处于打开状态。
至少一个手柄的初始状态是关闭的。

输出格式
第一行输出一个整数N,表示所需的最小切换把手次数。
接下来N行描述切换顺序,每行输入两个整数,代表被切换状态的把手的行号和列号,数字之间用空格隔开。

数据范围
1≤i,j≤4

输入样例:

-+--
----
----
-+--

输出样例:
6
1 1
1 3
1 4
4 1
4 3
4 4

注意:如果存在多种打开冰箱的方式,则按照优先级整体从上到下,同行从左到右打开

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

typedef pair<int, int> PII;
int change[4][4];

int get(int x, int y)
{
    return x * 4 + y;
}

int main()
{
    int state = 0;
    for(int i = 0; i < 4; i++) //用一个整数state表示4*4 的矩阵
    {
        string line;
        cin >> line;
        for(int j = 0; j < 4; j++)
            if(line[j] == '+')
                state += 1 << get(i, j); // get()函数改变状态
    }
    for(int i = 0; i < 4; i++) //操作某行某列的一个数转换为异或一个数的操作
        for(int j = 0; j < 4; j++)
        {
            for(int k = 0; k < 4; k++)
            {
                change[i][j] += 1 << get(i, k); //改变行
                change[i][j] += 1 << get(k, j); //改变列
            }
            change[i][j] -= 1 << get(i, j); // 加了两次,减去一次
        }
    vector<PII>res;
    for(int k = 0; k < 1 << 16; k++) //枚举所有情况一共2的16次方不同状态
    {
        int now = state;
        vector<PII>path;
        for(int i = 0; i < 16; i++)
            if(k >> i & 1) //k 的第 i位 是1 判断操作哪个格子,是1就操作
            {
                int x = i / 4, y = i % 4; //第i个格子的编号 x,y坐标
                now ^= change[x][y];
                path.push_back({x, y});
            }

        if(!now && ( res.empty() || res.size() > path.size()) ) res = path;
    }
    cout << res.size() << endl;
    for(auto p : res) cout << p.first + 1 << ' ' << p.second + 1 << endl;
    return 0;
}

117. 占卜DIY

达达学会了使用扑克DIY占卜。
方法如下:
一副去掉大小王的扑克共52张,打乱后均分为13堆,编号1~13,每堆4张,其中第13堆称作“生命牌”,也就是说你有4条命。
这里边,4张K被称作死神。
初始状态下,所有的牌背面朝上扣下。
流程如下:
1.抽取生命牌中的最上面一张(第一张)。
2.把这张牌翻开,正面朝上,放到牌上的数字所对应编号的堆的最上边。(例如抽到2,正面朝上放到第2堆牌最上面,又比如抽到J,放到第11堆牌最上边,注意是正面朝上放)
3.从刚放了牌的那一堆最底下(最后一张)抽取一张牌,重复第2步。(例如你上次抽了2,放到了第二堆顶部,现在抽第二堆最后一张发现是8,又放到第8堆顶部.........)
4.在抽牌过程中如果抽到K,则称死了一条命,就扔掉K再从第1步开始。
5.当发现四条命都死了以后,统计现在每堆牌上边正面朝上的牌的数目,只要同一数字的牌出现4张正面朝上的牌(比如4个A),则称“开了一对”,当然4个K是不算的。
6.统计一共开了多少对,开了0对称作”极凶”,1-2对为“大凶”,3对为“凶”,4-5对为“小凶”,6对为“中庸”,7-8对“小吉”,9对为“吉”,10-11为“大吉”,12为“满堂开花,极吉”。

输入格式
一共输入13行数据,每行四个数字或字母,表示每堆牌的具体牌型(不区分花色只区分数字),每堆输入的顺序为从上到下。
为了便于读入,用0代表10。
同行数字用空格隔开。

输出格式
输出一个整数,代表统计得到的开出的总对数。

输入样例:
8 5 A A
K 5 3 2
9 6 0 6
3 4 3 4
3 4 4 5
5 6 7 6
8 7 7 7
9 9 8 8
9 0 0 0
K J J J
Q A Q K
J Q 2 2
A K Q 2

输出样例:
9

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 14;

vector<int> cards[14];
int open[14];

int get(char c) //求每个符号表示的数字
{
    if( c == 'A') return 1;
    if( c >= '2' && c <= '9') return c - '0';
    if(c == '0') return 10;
    if(c == 'J') return 11;
    if(c == 'Q') return 12;
    return 13;
}

int main()
{
    for(int i = 1; i <= 13; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            char s[2]; //长度为2的字符串来读取字符 自动过滤回车制表符
            cin >> s;
            cards[i].push_back(get(*s)); //*s 等价于 s[0] 取第一个元素
        }
    }

    for(int i = 0; i < 4; i++)
    {
        int t = cards[13][i];
        while(t != 13)
        {
            open[t] ++;
            int r = cards[t].back(); // 返回最后一个元素
            cards[t].pop_back();
            t = r;
        }
    }

    int res = 0;
    for(int i = 1; i <= 12; i ++) res += open[i] >= 4;
    cout << res <<endl;
    return 0;
}

118. 分形

分形,具有以非整数维形式充填空间的形态特征。
通常被定义为“一个粗糙或零碎的几何形状,可以分成数个部分,且每一部分都(至少近似地)是整体缩小后的形状”,即具有自相似的性质。
现在,定义“盒子分形”如下:
一级盒子分形:

X

二级盒子分形:

   X X
    X
   X X

如果用B(n - 1)代表第n-1级盒子分形,那么第n级盒子分形即为:

  B(n - 1)        B(n - 1)

          B(n - 1)

  B(n - 1)        B(n - 1)

你的任务是绘制一个n级的盒子分形。

输入格式
输入包含几个测试用例。
输入的每一行包含一个不大于7的正整数n,代表要输出的盒子分形的等级。
输入的最后一行为-1,代表输入结束。

输出格式
对于每个测试用例,使用“X”符号输出对应等级的盒子分形。
请注意’X’是一个大写字母。
每个测试用例后输出一个独立一行的短划线。

输入样例:
1
2
3
4
-1

输出样例

X
-
X X
 X
X X
-
X X   X X
 X     X
X X   X X
   X X
    X
   X X
X X   X X
 X     X
X X   X X
-
X X   X X         X X   X X
 X     X           X     X
X X   X X         X X   X X
   X X               X X
    X                 X
   X X               X X
X X   X X         X X   X X
 X     X           X     X
X X   X X         X X   X X
         X X   X X
          X     X
         X X   X X
            X X
             X
            X X
         X X   X X
          X     X
         X X   X X
X X   X X         X X   X X
 X     X           X     X
X X   X X         X X   X X
   X X               X X
    X                 X
   X X               X X
X X   X X         X X   X X
 X     X           X     X
X X   X X         X X   X X
-
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1010;

char g[N][N];

void dfs(int n)
{
    if(n == 1)
    {
        g[0][0] = 'X';
        return;
    }

    dfs(n - 1);

    int len = 1;
    for(int i = 0; i < n-2; i++) len *=3; //求n-1级图形的边长 3^n-2

    int sx[4] = {0, 1, 2, 2}, sy[4] = {2, 1, 0, 2};
    for(int k = 0; k < 4; k ++)
        for(int i = 0; i < len; i++)
            for(int j = 0; j < len; j++)
                g[sx[k] * len + i][sy[k] * len + j] = g[i][j]; //复制
}

int main()
{
    dfs(7);

    int n;
    while(cin >> n, n != -1)
    {
        int len = 1;
        for(int i = 0; i < n - 1; i ++) len *= 3; //一级是1,二级是3,三级是9,n级是3的n-1次方
        for(int i = 0; i < len; i++)
        {
            for(int j = 0; j < len; j ++)
                if(g[i][j]) cout << 'X';
                else cout << ' ';
            cout << endl;
        }
        cout << '-' << endl; //短划线
    }
    return 0;
}

119. 袭击

在与联盟的战斗中屡战屡败后,帝国撤退到了最后一个据点。
依靠其强大的防御系统,帝国击退了联盟的六波猛烈进攻。
经过几天的苦思冥想,联盟将军亚瑟终于注意到帝国防御系统唯一的弱点就是能源供应。
该系统由N个核电站供应能源,其中任何一个被摧毁都会使防御系统失效。
将军派出了N个特工进入据点之中,打算对能源站展开一次突袭。
不幸的是,由于受到了帝国空军的袭击,他们未能降落在预期位置。
作为一名经验丰富的将军,亚瑟很快意识到他需要重新安排突袭计划。
他现在最想知道的事情就是哪个特工距离其中任意一个发电站的距离最短。
你能帮他算出来这最短的距离是多少吗?

输入格式
输入中包含多组测试用例。
第一行输入整数T,代表测试用例的数量。
对于每个测试用例,第一行输入整数N。
接下来N行,每行输入两个整数X和Y,代表每个核电站的位置的X,Y坐标。
在接下来N行,每行输入两个整数X和Y,代表每名特工的位置的X,Y坐标。

输出格式
每个测试用例,输出一个最短距离值,结果保留三位小数。
每个输出结果占一行。

数据范围
1≤N≤100000,
0≤X,Y≤1000000000

输入样例:
2
4
0 0
0 1
1 0
1 1
2 2
2 3
3 2
3 3
4
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0

输出样例:
1.414
0.000

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const int N = 200010;
const double INF = 1e10;

struct Point
{
    double x, y;
    bool type;
    bool operator< (const Point &W) const
    {
        return x < W.x;
    }
}points[N], temp[N];

double dist(Point a, Point b)
{
    if(a.type == b.type) return INF;
    double dx = a.x - b.x, dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
}

double dfs(int l, int r)
{
    if(l >= r) return INF;//当前区间最多只有一个元素
    int mid = l + r >> 1;
    double mid_x = points[mid].x; //分界线
    double res = min(dfs(l, mid), dfs(mid + 1, r)); // 递归左边和右边
    //变量作用域,限制在括号里面
    {
        //归并排序
        int k = 0, i = l, j = mid + 1; //i = L
        while(i <= mid && j <= r)
            if(points[i].y < points[j].y) temp[k++] = points[i++];
            else temp[k++] = points[j++];
        while(i <= mid) temp[k++] = points[i++];
        while(j <= r) temp[k++] = points[j++];

        for(i = 0, j = l; i < k; i++, j++) points[j] = temp[i]; //把临时数据放回去 j从 L开始循环
    }

    int k = 0;
    for(int i = l; i <= r; i++) //i = L
        if(points[i].x >= mid_x - res && points[i].x <= mid_x + res)
            temp[k++] = points[i];

    for(int i = 0; i <= k; i++)
        for(int j = i - 1; j >=0 && temp[i].y - temp[j].y <= res; j --)
            res = min(res, dist(temp[i], temp[j]));

    return res;
}

int main()
{
    int T, n;
    cin >> T;
    while(T --)
    {
        cin >> n;
        for(int i = 0; i < n; i++)
        {
            cin >> points[i].x >> points[i].y;
            points[i].type = 0;
        }
        for(int i = n; i < n * 2; i++) //这里 i 由 n 到 n * 2
        {
            cin >> points[i].x >> points[i].y;
            points[i].type = 1;
        }

        sort(points, points + n * 2);
        printf("%.3f\n", dfs(0, n * 2 - 1));
    }
    return 0;
}

120. 防线

达达学习数学竞赛的时候受尽了同仁们的鄙视,终于有一天......受尽屈辱的达达黑化成为了黑暗英雄怪兽达达。
就如同中二漫画的情节一样,怪兽达达打算毁掉这个世界。
数学竞赛界的精英 lqr 打算阻止怪兽达达的阴谋,于是她集合了一支由数学竞赛选手组成的超级行动队。
由于队员们个个都智商超群,很快,行动队便来到了怪兽达达的黑暗城堡的下方。
但是,同样强大的怪兽达达在城堡周围布置了一条“不可越过”的坚固防线。
防线由很多防具组成,这些防具分成了 N 组。
我们可以认为防线是一维的,那么每一组防具都分布在防线的某一段上,并且同一组防具是等距离排列的。

也就是说,我们可以用三个整数 S, E 和 D 来描述一组防具,即这一组防具布置在防线的 S,S + D,S + 2D,…,S + KD(K∈ Z,S + KD≤E,S + (K + 1)D>E)位置上。

黑化的怪兽达达设计的防线极其精良。如果防线的某个位置有偶数个防具,那么这个位置就是毫无破绽的(包括这个位置一个防具也没有的情况,因为 0 也是偶数)。

只有有奇数个防具的位置有破绽,但是整条防线上也最多只有一个位置有奇数个防具。

作为行动队的队长,lqr 要找到防线的破绽以策划下一步的行动。

但是,由于防具的数量太多,她实在是不能看出哪里有破绽。作为 lqr 可以信任的学弟学妹们,你们要帮助她解决这个问题。

输入格式
输入文件的第一行是一个整数 T,表示有 T 组互相独立的测试数据。
每组数据的第一行是一个整数 N。
之后 N 行,每行三个整数 Si,Ei,Di,代表第 i 组防具的三个参数,数据用空格隔开。

输出格式
对于每组测试数据,如果防线没有破绽,即所有的位置都有偶数个防具,输出一行 "There‘s no weakness."(不包含引号) 。
否则在一行内输出两个空格分隔的整数 P 和 C,表示在位置 P 有 C 个防具。当然 C 应该是一个奇数。

数据范围
防具总数不多于10^8,
Si≤Ei,
1≤T≤5,
N≤200000,
0≤Si,Ei,Di≤231?1

输入样例:
3
2
1 10 1
2 10 1
2
1 10 1
1 10 1
4
1 10 1
4 4 1
1 5 1
6 10 1

输出样例:
1 1
There‘s no weakness.
4 3

#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;
const int N = 200010;

struct Seq
{
    int s, e, d; //起点 终点 公差
}seqs[N];

int n;

LL get_sum(int x)
{
    LL res = 0;
    for(int i = 0; i < n; i++)
        if(seqs[i].s <= x)
            //        上界              初始值(首项)  公差
            res += (min(seqs[i].e, x) - seqs[i].s) / seqs[i].d + 1; //*****
    return res;        

}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int l = 0, r = 0;
        scanf("%d", &n);
        for(int i = 0; i < n; i++)
        {
            int s, e, d;
            scanf("%d%d%d", &s, &e, &d);
            seqs[i] = {s, e, d};
            r = max(r, e); //最大值
        }
        while(l < r)
        {
            int mid = l + r >> 1;
            if(get_sum(mid) & 1) r = mid; // mid & 1等价于 mid % 2 是奇数,在左半边
            else l = mid + 1;

        }

        auto sum = get_sum(r) - get_sum(r - 1); //r个数
        if(sum % 2) printf("%d %lld\n", r, sum); //Linuxx系统用%lld Windows系统 %I64d
        else puts("There's no weakness.");
    }
    return 0;
}

121. 赶牛入圈

农夫约翰希望为他的奶牛们建立一个畜栏。
这些挑剔的畜生要求畜栏必须是正方形的,而且至少要包含C单位的三叶草,来当做它们的下午茶。
畜栏的边缘必须与X,Y轴平行。
约翰的土地里一共包含N单位的三叶草,每单位三叶草位于一个1 x 1的土地区域内,区域位置由其左下角坐标表示,并且区域左下角的X,Y坐标都为整数,范围在1到10000以内。
多个单位的三叶草可能会位于同一个1 x 1的区域内,因为这个原因,在接下来的输入中,同一个区域坐标可能出现多次。
只有一个区域完全位于修好的畜栏之中,才认为这个区域内的三叶草在畜栏之中。
请你帮约翰计算一下,能包含至少C单位面积三叶草的情况下,畜栏的最小边长是多少。

输入格式
第一行输入两个整数 C 和 N。
接下来 N 行,每行输入两个整数 X 和 Y,代表三叶草所在的区域的X,Y坐标。
同一行数据用空格隔开。

输出格式
输出一个整数,代表畜栏的最小边长。

数据范围
1≤C≤500,
C≤N≤500

输入样例:
3 4
1 2
2 1
4 1
5 2

输出样例:
4

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

typedef pair<int, int> PII;
const int N = 1010;

int n, C;
PII points[N];
vector<int> numbers; // 离散化后的数
int sum[N][N]; // 前缀和

int get(int x)
{
    int l = 0, r = numbers.size() - 1;
    while(l < r)
    {
        int mid = l + r >> 1;
        if(numbers[mid] >= x) r = mid;
        else l = mid + 1;
    }
    return r;
}

bool check(int len)
{
    for(int x1 = 0, x2 = 1; x2 < numbers.size(); x2++)
    {
        while(numbers[x2] - numbers[x1 + 1] + 1 > len) x1++;
        for(int y1 = 0, y2 = 1; y2 < numbers.size(); y2 ++)
        {
            while(numbers[y2] - numbers[y1 + 1] + 1 >len) y1++;
            if(sum[x2][y2] - sum[x1][y2] - sum[x2][y1] + sum[x1][y1] >= C)
                return true;
        }
    }
    return false;
}

int main()
{
    cin >> C >> n;
    numbers.push_back(0);
    for(int i = 0; i < n; i++)
    {
        int x, y;
        cin >> x >> y;
        points[i] = {x, y};
        numbers.push_back(x);
        numbers.push_back(y);
    }

    sort(numbers.begin(), numbers.end());
    numbers.erase(unique(numbers.begin(), numbers.end()), numbers.end()); //把迭代器之间的相同元素放在最后,返回一个迭代器,
    //输出是最后一个不相同元素的位置,作用是删除重复元素
    for(int i = 0; i < n; i++)
    {
        //离散化
        int x = get(points[i].first), y = get(points[i].second);
        sum[x][y]++;
    }

    //前缀和
    for(int i = 1; i < numbers.size(); i++)
        for(int j = 1; j < numbers.size(); j++)
            sum[i][j] += sum[i-1][j] + sum[i][j - 1] - sum[i-1][j-1]; //矩形前缀和,二维前缀和

    int l = 1, r = 10000;
    while(l < r)
    {
        int mid = l + r >> 1;
        if(check(mid)) r = mid;
        else l = mid + 1;
    }

    cout << r << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/wmxnlfd/p/10874046.html

时间: 2024-10-29 14:36:22

《算法竞赛进阶指南》0.8总结与练习(1)的相关文章

《算法竞赛进阶指南》学习总结 #include&lt;algorithm&gt;

今天下午大致学完了进阶指南中algorithm头文件下的内容,在这里进行一个总结.   reverse翻转   顾名思义,reverse进行的操作就是翻转原来的顺序,理解非常简单,故不赘述. 操作样例: #include<bits/stdc++.h> using namespace std; vector<int>a; int b[233]; int main() { int na,nb; //vector的实现 scanf("%d",&na); for

《算法竞赛进阶指南》学习总结 二分与三分

首先......我是一个很菜很菜的萌新,所以这篇文章写得很详细,有很多我自己的口水话方便我理解,请各位谨慎食用qwq 以前在网上找过很多介绍二分的博客,但都感觉对萌新不太友好,反正我当时连跳石头都没看懂,所以决定自己写一篇!其中有我的想法,也借鉴了书里的很多内容,感谢lyd. 二分答案,顾名思义,就是对我们所需要的答案进行二分,对我们要求的值进行二分.二分的基础用法是在单调序列或者单调函数当中查找,当答案具有单调性,我们就可以采用二分来计算,当然还有三分,在后面我会详细讲到 整数集合上的二分 在

《算法竞赛进阶指南》0.4二分

102. 最佳牛围栏 农夫约翰的农场由N块田地组成,每块地里都有一定数量的牛,其数量不会少于1头,也不会超过2000头. 约翰希望用围栏将一部分连续的田地围起来,并使得围起来的区域内每块地包含的牛的数量的平均值达到最大. 围起区域内至少需要包含 F块地,其中 F会在输入中给出. 在给定条件下,计算围起区域内每块地包含的牛的数量的平均值可能的最大值是多少. 输入格式 第一行输入整数 N和 F,数据间用空格隔开. 接下来 N行,每行输出一个整数,第i+1行输出的整数代表,第i片区域内包含的牛的数目.

《算法竞赛进阶指南》0.6倍增

109. 天才ACM 给定一个整数 M,对于任意一个整数集合 S,定义"校验值"如下: 从集合 S中取出 M 对数(即 2?M 个数,不能重复使用集合中的数,如果 S 中的整数不够 M 对,则取到不能取为止),使得"每对数的差的平方"之和最大,这个最大值就称为集合 S的"校验值". 现在给定一个长度为 N的数列 A 以及一个整数 T. 我们要把 A分成若干段,使得每一段的"校验值"都不超过 T. 求最少需要分成几段. 输入格式

算法竞赛进阶指南 走廊泼水节

原题链接 题目描述 给定一棵N个节点的树,要求增加若干条边,把这棵树扩充为完全图,并满足图的唯一最小生成树仍然是这棵树. 求增加的边的权值总和最小是多少. 输入格式 第一行包含整数t,表示共有t组测试数据. 对于每组测试数据,第一行包含整数N. 接下来N-1行,每行三个整数X,Y,Z,表示X节点与Y节点之间存在一条边,长度为Z. 输出格式 每组数据输出一个整数,表示权值总和最小值. 每个结果占一行. 数据范围 \(N \le 6000,Z \le 100\) 输入样例: 2 3 1 2 2 1

bzoj 1787 &amp;&amp; bzoj 1832: [Ahoi2008]Meet 紧急集合(倍增LCA)算法竞赛进阶指南

题目描述 原题连接 Y岛风景美丽宜人,气候温和,物产丰富. Y岛上有N个城市(编号\(1,2,-,N\)),有\(N-1\)条城市间的道路连接着它们. 每一条道路都连接某两个城市. 幸运的是,小可可通过这些道路可以走遍Y岛的所有城市. 神奇的是,乘车经过每条道路所需要的费用都是一样的. 小可可,小卡卡和小YY经常想聚会,每次聚会,他们都会选择一个城市,使得3个人到达这个城市的总费用最小. 由于他们计划中还会有很多次聚会,每次都选择一个地点是很烦人的事情,所以他们决定把这件事情交给你来完成. 他们

《算法竞赛进阶指南》打卡活动 #0x00 基本算法

101. 最高的牛 题目链接:https://www.acwing.com/problem/content/103/ 作为一个银牌水平的主演数据结构的演员来说,这题现在发现非常好想,每个牛分配一个优先度.我搞一个区间线段树,每次update中间一段使得他们的优先度整体下降到比两端中较小的优先度还要小.然后反过来按照优先度分配身高.哈哈!根本不需要什么算法.不过每次都不询问为什么要线段树呢?差分不香吗?当然不香,每次询问当前的优先度啊! const int MAXN = 10000; int re

【算法竞赛进阶指南】USACO07Tallest Cow

前缀和,利用左右端点操作代替对区间的操作,从而优化输入,最后进行一次前缀和的操作,求得结果,这道题里面有个很关键的问题,就是需要去重,本来我想用set,但貌似有点鬼畜,算了,利用map去重,还有pair类型(学一下) #include <iostream> #include <algorithm> #include <map> #include <utility> using namespace std; map<pair<int,int>

【算法竞赛进阶指南】POJ1845Sumdiv

本题目是一道数论的综合题目,主要的一个点就是利用二分法来求等比数列的和,其余的点就是唯一分解定理分解质因数,还有就是快速幂 A^B约数和\(=(1+p_{1}+p_{1}^{2}+\cdot\cdot\cdot+p_{1}^{c1})*(1+p_{2}+p_{2}^{2}+\cdot\cdot\cdot+p_{2}^{c2})*\cdot\cdot\cdot*(1+p_{n}+p_{n}^{2}+\cdot\cdot\cdot+p_{n}^{cn})\) 如果c是奇数(一共有偶数项)\(sum(