现在的位置: 首页 > 综合 > 正文

BZOJ 2833(数列对计数-分段Dp)

2014年10月24日 ⁄ 综合 ⁄ 共 1830字 ⁄ 字号 评论关闭

2833: 数列对计数

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 19  Solved: 12
[Submit][Status][Discuss]

Description

考虑两个数列整数列A = {a[1], a[2], …, a[n]} and B = {b[1], b[2], …, b[n]},如果从两个数列中各取一项a[i]b[j],其和各不相同且全部在[1,n*n]内,则称(A,B)是一个数列对。求本质不同的数列对数。

如果两个数列对在进行以下操作或以下若干操作的组合后相同,那么则认为他们是本质相同的:

交换AB

A的每个数减一常数,B的每个数加一常数;

交换A中或B中任意两个数。

所以,你可以认为a[1]=0b[1]=1A,B均按升序排列。

Input

第一行一个整数T表示测试数据个数;

以下T行每行一个整数n表示序列的长度。

Output

对于每个测试数据输出一行,表示本质不同的数列对个数。

Sample Input

4

1

2

3

4

Sample Output

1

1

1

3

HINT

N=4时,本质不同的数列对有3个:

(A={0,1,2,3}, B={1,5,9,13})

(A={0,1,4,5}, B={1,3,9,11})

(A={0,1,8,9}, B={1,3,5,7})

【数据规模及约定】

对于100%的数据,n<=1000。

 

Source

手算发现符合条件的数列都为

XX....XX.....XX.....XX........

假设相邻X的长度为t


F[H,n,s]表示长度为h的区间,放n个X,其中s=0表示t=1,s=1表示t>1

于是记忆化搜索。

s=1 暴力枚举t


s=0 根据一一对应关系,转成F[H,H/n,1]

初始状态是n=1(只有一个X)

此时唯一的排法是A={1,2,3,..,h},B={0}

所以F[H,1,0]=1 F[h,1,1]=0

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
#include<map>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define MAXN (2000+10)
int T,n;
struct node
{
    int h,n;
    bool s;
    node(){}
    node(int _h,int _n,bool _s):h(_h),n(_n),s(_s){}
    friend bool operator<(node a,node b){if (a.h^b.h) return a.h<b.h;if (a.n<b.n) return a.n<b.n;if (a.s<b.s) return a.s<b.s;}
};
map< node ,long long> f;
long long dfs(int h,int n,bool s) /*总长,取数 s=0 循环节=1;s=1 循环节>1*/
{
    node a=node(h,n,s);
    if (f.find(a)!=f.end()) return f[a];
    if (!s) return f[a]=(n==1?1:dfs(h,h/n,1));
    if (n==1) return f[a]=0;
    long long ans=0;
    For(t,sqrt(n))
        if (n%t==0)
        {
            if (t>1) ans+=dfs(h/t,n/t,0);
            if (t*t<n) ans+=dfs(h/(n/t),t,0);
        }
    return f[a]=ans;
}
int main()
{
//	freopen("bzoj2833.in","r",stdin);
    cin>>T;
    while (T--)
    {
        scanf("%d",&n);
        if (n==1) cout<<"1"<<endl;
        else cout<<dfs(n*n,n,1)<<endl;
    }

	return 0;
}



抱歉!评论已关闭.