【刷题】序列问题

时间:2019-08-29
本文章向大家介绍【刷题】序列问题,主要包括【刷题】序列问题使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题面在此

 然后

方案1:

裸上,N^3

#include<cstdio>
#include<cstdlib>
using namespace std;
int n;
const int N=103,M=1024;
int d[N];

int back[N][M];
void get_back(int nw,int pre,int x)
{
    for(int i=0;i<1024;i++)
        if(back[pre][i])
            back[nw][i]+=back[pre][i],back[nw][i&x]+=back[pre][i];
    back[nw][x]++;
}

int front[N][M];
void get_front(int nw,int pre,int x)
{
    for(int i=0;i<1024;i++)
    {
        for(int j=pre;j;j--)    
            front[nw][i^x]+=front[j][i];    
    }
    front[nw][x]++;
}

long long ans;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&d[i]);
    
    for(int i=n-1;i;i--)
        get_back(i,i+1,d[i+1]);
    for(int i=1;i<n;i++)
        get_front(i,i-1,d[i]);
    
    for(int i=1;i<n;i++)
    {
        for(int j=0;j<1024;j++)
            if(front[i][j]) ans+=back[i][j]*front[i][j];
    }
    printf("%lld\n",ans);
    
    return 0;
}

方案二:

DP,解法真的很有意思

一个重要的发现:
两个数相等就是,两个数异或等于0

所以就可以把问题化简
求一个长度为n的序列中,选择至少两个数,
将数设为a1,a2,a3...ai...aj
使a1^a2^a3^...^ai & ai+1 & ... aj
结果为0

这里减少的是一个枚举i,
和一个分别枚举1024*n的复杂度

#include<cstdio>
#include<cstdlib>
using namespace std;
int n;
const int N=1003;
int d[N];
long long f[N][1024][2];//这个0,1表示这一次进行的运算 & ^ 

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&d[i]);
    
    f[n][d[n]][0]=1; 
    for(int i=n-1;i;i--)
    {    
        for(int j=0;j<1024;j++)
        {
            f[i][j][0]+=f[i+1][j][0];
            f[i][j][1]+=f[i+1][j][1];
            
            f[i][j^d[i] ][1] +=f[i+1][j][1]+f[i+1][j][0]; 
            f[i][j&d[i] ][0] +=f[i+1][j][0];
        }
        f[i][d[i]][0]++; 
    }
    
    printf("%lld\n",f[1][0][1]);
    return 0;
}

估算一下答案的范围,特别大,

(虽然我其实不会估算)

反正肯定加爆了,需要压位高精度

代码等会上

原文地址:https://www.cnblogs.com/xwww666666/p/11432027.html