Lucas定理的应用

来源:互联网 发布:JS域名代码授权源码 编辑:程序博客网 时间:2024/05/17 06:00

题意:有n盏灯环形排列,顺时针依次标号为1⋯n。初始时刻为0,初始时刻第i盏灯的亮灭a[i]给定,0表示灭,1表示亮。下一时刻每盏灯的亮灭取决于当前时刻这盏灯与顺时针方向下一盏灯的亮灭。若两盏灯状态相同,则下一时刻该灯灭,否则该灯亮。求时刻t第k盏灯的状态。
(n,t,k≤1e7)
Solution:
异或可以看成不进位的二进制加法,于是我们可以先做出一个图找找规律:

可见,对于第i个数,在执行t步操作后对第一个数的贡献为(可以转化成一共走t步,每次向下或者向左下,其中有i次向左下的方案数),因为模数是2,所以如果是偶数,那么这个数相当于是没有贡献的,所以我们就得到了答案:(所有下标-1)
但是我们发现还要求组合数,这样太慢了,我们要追求更快的做法!
这里就要用到Lucas定理了:
根据公式可以看出,当p=2时,只有n%p=1且m%p=0时,为偶数,所以说n所对应的m的每一位都不能出现上述情况,即(n&m==n),因此,如果(n&m==n),,这个问题就解决了。

代码:

#include<cstdio>#include<iostream>using namespace std;int n,t,k;int ans=0;int a[3000010];int main(){    scanf("%d%d%d",&n,&t,&k);    k--;     for (int i=0;i<n;i++)        scanf("%d",&a[i]);    for (int i=0;i<=t;i++)    {        if ((i&t)==i) ans+=a[(i+k)%n];    }    printf("%d",ans%2);} 
原创粉丝点击