计蒜客暑假集训第一阶段第六场 j题 set

Let's consider some math problems.

JSZKC has a set A=\{1,2,...,N\}A={1,2,...,N}. He defines a subset of AA as 'Meo set' if there doesn't exist two integers in this subset with difference one. For example, When A=\{1,2,3\}, \{1\},\{2\},\{3\},\{1,3\}A={1,2,3},{1},{2},{3},{1,3} are 'Meo set'.

For each 'Meo set', we can calculate the product of all the integers in it. And then we square this product. At last, we can sum up all the square result of the 'Meo set'.

So please output the final result.

Input Format

The input file contains several test cases, each of them as described below.

  • The first line of the input contains one integers NN (1 \le N \le 100)(1≤N≤100), giving the size of the set.

There are no more than 100100 test cases.

Output Format

One line per case, an integer indicates the answer.

样例输入

3

样例输出

23

题目大意:

题目大意:给定一个数字n,代表有一个集合是(1,2,3.......n),让你找该集合的子集,子集满足的条件:子集中只有一个元素或者子集中的元素任意两个的差必须大于一,这两个条件只满足其中一个就可以。然后对子集中的元素先相乘,然后平方,累加。

题目中给出的例子:n等于3        子集:(1),(2),(3),(1,3)

那么结果就是:1^2+2^2+3^2+(1*3)^2=23。

思路:

我们拿5举例子,通过上图发现,5的所有满足条件的子集中,有7个是4的子集(图中不划线的集合),然后剩余的集合(划线的集合)都有一个5,当你把剩余的集合中的5去掉以后,除了只有一个5的集合外,其他的集合就是3的子集,至此,规律很明显了。    F(5)=F(4)+F(3)*(5*5)+(5*5)。

总结一下,对于任意n,我们有如下递推公式:

F(n)=F (n-1)+F(n-2)*(n*n)+(n*n)。

不过,由于此题最后的结果很大,所以要高精度才能够正确输出结果。

代码如下:

#include<bits/stdc++.h>
using namespace std;
int n;
string dp[101];
const int L=11000;
string convertInt(int number)//将number转化为字符串
{
   stringstream ss;
   ss << number;
   return ss.str();
}
string add(string a,string b)//只限两个非负整数相加
{
    string ans;
    int na[L]={0},nb[L]={0};
    int la=a.size(),lb=b.size();
    for(int i=0;i<la;i++) na[la-1-i]=a[i]-'0';
    for(int i=0;i<lb;i++) nb[lb-1-i]=b[i]-'0';
    int lmax=la>lb?la:lb;
    for(int i=0;i<lmax;i++) na[i]+=nb[i],na[i+1]+=na[i]/10,na[i]%=10;
    if(na[lmax]) lmax++;
    for(int i=lmax-1;i>=0;i--) ans+=na[i]+'0';
    return ans;
}
string mul(string a,string b)//高精度乘法a,b,均为非负整数
{
    string s;
    int na[L],nb[L],nc[L],La=a.size(),Lb=b.size();
    fill(na,na+L,0);fill(nb,nb+L,0);fill(nc,nc+L,0);
    for(int i=La-1;i>=0;i--) na[La-i]=a[i]-'0';
    for(int i=Lb-1;i>=0;i--) nb[Lb-i]=b[i]-'0';
    for(int i=1;i<=La;i++)
        for(int j=1;j<=Lb;j++)
        nc[i+j-1]+=na[i]*nb[j];
    for(int i=1;i<=La+Lb;i++)
        nc[i+1]+=nc[i]/10,nc[i]%=10;
    if(nc[La+Lb]) s+=nc[La+Lb]+'0';
    for(int i=La+Lb-1;i>=1;i--)
        s+=nc[i]+'0';
    return s;
}
int main()
{
    dp[1]='1';//先给dp[1],dp[2]赋初值,这里必须是字符串,不能是整数
    dp[2]='5';
    for(int i=3;i<=100;i++)//我们把所有结果都算出来,直接从dp数组中拿即可
    {
        string a=convertInt(i*i);
        dp[i]=add(add(dp[i-1],a),mul(dp[i-2],a));
    }
    while (scanf("%d",&n)!=EOF)
    {
        cout<<dp[n]<<endl;
    }
}


收获:

一:知道了高精度如何计算,找到了几个关于大数运算模板。

二:对于一些输入单个数字,输出也是单个数字(输入和输出是一一对应)的题目,一般就是寻找规律,递推求解。

猜你喜欢

转载自blog.csdn.net/qq_40938077/article/details/81296310