UOJ Logo zhouzixuan的博客

博客

bzoj 4414: 数量积

2016-03-01 16:26:42 By zhouzixuan
【题目描述】:
    神犇heheda最近得到了UOJ抱枕,蒟蒻yts1999想要玩。于是heheda给yts1999出了一道题:
    一个长度为2n+2的整数数列 按照下式定义:
    A0=0
    A1=C
    Ai+2=(Ai+1+Ai) Mod M (0<=i<=2*N)
    现有n个平面向量v1…vn:
    V1=(A2,A3),V2=(A4,A5)...Vn=(A2n,A2n+1)
    集合S的定义如下:

    其中"vi•vj"表示向量vi和vj的数量积。
    求S集合中不同元素的个数是多少。答案对M取模。
    heheda告诉yts1999,只要他做出了这道题,她就可以把抱枕借给他玩一会。然而yts1999实在是太弱了不会做,于是向你求助。
【题目解法】:
    根据类斐波那契数列的性质:
    F[1]*F[n+m+1]=F[n]*F[m]+F[n+1]*F[m+1]
    F[1]*F[n+1]=F[m]*F[n-m]+F[m+1]*F[n-m+1]
    因此对于两个向量:vi=(F[i],F[i+1]) vj=(F[j],F[j+1])
    那么F[i]*F[j]+F[i+1]*F[j+1]=F[1]*F[i+j+1]
    因此对于所有就是询问本质不同的F[i+j+1]*F[1]
    i+j+1的范围是[7,4n-1]内所有的奇数,全部拉出来sort一发就好
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=2000005;
int n,maxmod,f[N],a[N],tot;
inline long long getint()
{
    long long x=0; char c=getchar(); bool flag=false;
    while ((c!='-')&&((c<'0')||(c>'9'))) c=getchar();
    if (c=='-') flag=true,c=getchar();
    while ((c>='0')&&(c<='9')) x=x*10+(long long)(c-'0'),c=getchar();
    if (flag) return -x; else return x;
}
void init()
{
    f[1]=getint(); maxmod=getint(); n=getint(); tot=0;
    for (int i=2; i<=4*n; i++) f[i]=(f[i-1]+f[i-2])%maxmod;
    for (int i=6; i<=4*n-2; i+=2) a[++tot]=(long long)f[i+1]*f[1]%maxmod;
}
void solve()
{
    sort(a+1,a+tot+1);
    tot=unique(a+1,a+tot+1)-(a+1);
    printf("%d\n",tot%maxmod);
}
int main()
{
    init();
    solve();
    return 0;
}

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。