【bzoj3823】【定情信物】【递推】

Description

都说程序员找不到妹子,可是无人知晓,三生石上竟然还刻着属于小 E 的一笔。

那一天, E 穷尽毕生的积蓄,赠与了妹子一个非同寻常的定情信物。那是一个小

小的正方体,但透过它,可以看到过去,可以洞彻天机。

这份信物仿佛一只深邃的眼。当看透它看似简单的外表后,深邃的内心却最是可以

叩击人的灵魂的。不出所料,妹子果然被这个信物超越空间的美所吸引。

易有太极,是生两仪,两仪生四象,四象生八卦。,八卦定吉凶,吉凶生大业。

这句箴言在其上得到了完美的诠释。

是的,这正是一个超正方体。

 E 告诉妹子,他的情意也如这份信物一样深厚。现在妹子想知道, E 对她的情

意究竟有几分?

我们知道,点动成线,线动成面,面动成体...... n 维超立方体可看作由 n-1 维超

立方体沿垂直于它的所有的棱的方向平移得到的立体图形。

我们可以将点看作 0 维超立方体,将直线看作 1 维超立方体,将正方形看作 2 维超

立方体......依此类推。

任何一个 n 维超立方体(n>0)都是由低维的超立方体元素组成的:它的 n-1 维表面

 n-1 维的超立方体,它的 n-2 维边缘是 n-2 维的超立方体,它的 n-3 维元素是 n-3 维的

超立方体......

 E 对妹子的情意即为在他的定情信物——K 维超立方体中,含有每一维的元素个

数。由于元素个数可能较大,只需要输出它所包含的每一维元素个数模 P 后的异或和。

Input

两个整数 KP,详见题目叙述。

Output

一个非负整数,表示小 E 的定情信物所包含的每一维元素个数模 P 后的异或和。注

:异或和可能会大于 P

Sample Input

input 1
3 7

Input 2

4 2333

Input 3

12 7723

Sample Output

Output1

3

Output 2

33

Output 3

360

Hint
对于样例2的解释:
一个三维超立方体含有 8 个零维元素、12 个一维元素、6 个二维元素、1 个三维

元素,模 7 后分别为 1,5,6,1,异或和为 1^5^6^1=3。

HINT

对于 100%的数据,N≤10^7,P 为 10^9 内的素数。
题解:
          设f(0)表示在K维空间下0维元素的个数.
          显然
                  f(0)=2^k;
          一个x维的元素在k维空间中可以扩展出(k-x)个(x+1)维的元素.
          2*(x+1)个x维元素可以确定一个(x+1)维的元素.
          所以
                  f(1)=(k*f(0))/2;
                  f(2)=((k-1)*f(1))/4;
                  f(x+1)=((k-x)*f(x))/(2*(x+1));
         然后递推即可.我貌似是反着推的..
         注意p有可能会小于n.
         所以需要把参与运算的数分解为a*p^b的形式.
  代码:
#include<iostream>
#include<cstdio>
#define N 10000010
using namespace std;
int n;
long long inv[N],t,ans,P,temp,aa,x,y;
struct use{int a,b;};
void pre(){
  inv[1]=1;
  for(int i=2;i<=n&&i<P;i++)
    inv[i]=(P-P/(long long)i*inv[P%i]%P); 	
}
use cal(int x){
   int t(0);
   while (x%P==0) {t++;x/=P;};	
   return use{x,t};
}
int main(){
  scanf("%d%lld",&n,&P);
  pre();
  t=1;ans^=t;aa=n*2;x=1;y=0;
  for (int i=1;i<=n;i++){
    use a=cal(aa),b=cal(i);
    x=(long long)x*a.a%P;y=y+a.b;
    x=(x*inv[(b.a)%P])%P;y=y-b.b;
	if (!y) ans^=x;
    aa-=2;
  }
  cout<<ans<<endl;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值