Kattis - barcode

题目原文:

To prepare for ACM-ICPC 2017 in Saigon, the host univeristy – Ho Chi Minh city University of Education (HCMUE) – decided to print barcodes on the participants’ t-shirts. The barcode requirement needs to be simple to reduce the cost but still show some scientific style. HCMUE decided that every barcode consists of red bars and blue bars satisfing at least one of the following conditions:

l The number of blue bars is equal to the number of red bars.

l There are no 22 consecutive blue bars.

Let K denote the number of different ways to create the required barcodes containing bars. Given two integers and M, where M is a prime number, your task is to help them identify the remainder of divided by M.

Input

The input consists of several datasets. The first line of the input contains the number of datasets, which is a positive number and is not greater than 20. Each dataset is described by one line containing two numbers N and M (1≤N≤106,1<M≤107). M is a prime number.

Output

For each dataset, write in one line the remainder of K divided by M.

题目大意:

为一个长度为n的条形码制定一个涂色方案(红色和蓝色两种),要求满足下列条件之一:

  1. 红色和蓝色数量相等
  2. 蓝色条形码不连续

输出方案数(对素数M取余)

题目解析:

  1. 对于给出的样例很容易发现这是个Fibnaci数列的一部分,但是如果写出当N=4时的情况,发现结果为11,不是Fibnaci预期中的8。如果你继续验证会发现,当N为奇数时,结果是个Fibnaci数,当N为偶数,总比Fibnaci数大。
  2. 偶数与奇数的不同是偶数可以整除2,也就是偶数可以满足第一种情况,而奇数不可以;打表或者自己写出当N=4,6,8的情况,也可以验证多出的数字就是当红色等于蓝色时,条形码连续的情况。(注意当颜色相同时,也会有蓝色条形码不连续的情况,根据结果。这时默认是符合第二种情况的)
  3. 只需计算这个数即可。

    得:数量相等且连续 = 数量相等 - 数量相等且不连续;

    利用组合数: ans   = C(n,n/2) - C(n/2+1,n/2)

              = C(n,n/2) - C(n/2+1,1)

              = C(n,n/2) - n/2 - 1

    当N为奇数 res = F[n]%M(不是完整的Fibnaci,要从F[1] = 2,F[2] = 3开始计算)

    当N为偶数 res = (F[n] + ans)%M

    程序涉及了Lucas定理和逆元

   参考博客:https://www.cnblogs.com/fzl194/p/9095177.html

         https://www.cnblogs.com/scx2015noip-as-php/p/lucas.html

AC代码:

    

 #include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e6 + ;
LL f[maxn];
template<typename T>
T pow_mod(T a,T b,T c)
{
T ans = ;
a %= c;
while(b)
{
if(b&) ans = (ans*a)%c;
b >>= ;
a = (a*a)%c;
}
return ans;
}
template<typename T>
T inv(T x,T p)
{
return pow_mod(x,p-,p);
}
template<typename T>
T C(T n,T m,T p)
{
if(m > n) return ;
if(m == ||m == n) return ;
if(m == ||m == n-) return n;
m = min(m,n-m);
T up = ,down = ;
for(int i=n-m+;i<=n;i++) up = (up*i)%p;
for(int i=;i<=m;i++) down = (down*i)%p;
return (up * inv(down,p))%p;
}
template<typename T>
T Lucas(T n,T m,T p)
{
if(m == ) return ;//边界
return (Lucas(n/p,m/p,p) * C(n%p,m%p,p))%p;
}
//同下
//template<typename T>
//T Lucas(T n,T m,T p)
//{
// T ans = 1;
// while(m)
// {
// ans = (ans * C(n%p,m%p,p))%p;
// n /= p;
// m /= p;
// }
// return ans;
//}
LL Fibnaci(LL n,LL mod)
{
f[] = ;
f[] = ;
for(int i=;i<=n;i++)
f[i] = (f[i-] + f[i-])%mod;
return f[n];
} int main()
{
int T;
LL n,m;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld",&n,&m);
if(n & )
{
cout << Fibnaci(n,m) << endl;
}
else
{
cout << (((Fibnaci(n,m) + Lucas(n,n/,m) - (n/ + ))%m)+m)%m << endl;
}
}
return ;
}

最新文章

  1. opendrive
  2. Linux查找含有某字符串的所有文件
  3. PRML读书笔记——2 Probability Distributions
  4. XSS 自动化检测 Fiddler Watcher &amp; x5s &amp; ccXSScan 初识
  5. yii框架中邮箱激活(数字签名)
  6. .Net验证码实现基础--Draw
  7. Linux内存分配----SLAB
  8. sqlserver防止数据库挂马新尝试
  9. java strtus2 DynamicMethodInvocation配置入门 &quot; ! &quot;访问action里面的方法
  10. Swift开发之 ---- Swift宏定义
  11. FileZilla 425 Can&#39;t open data connection
  12. 观察者模式与Boost.Signals
  13. docker 内部组件结构 -- docker daemon, container,runC
  14. Hibernate中的对象有三种状态
  15. VUE之图表操作
  16. jquery库的cookie用法
  17. What can Reactive Streams offer EE4J?
  18. django模版之过滤器
  19. tiny6410采用sd卡烧写的问题
  20. 《Agile Web Development With Rails》读后感--rails基于web设计的best Practices

热门文章

  1. Markdown ![...](...) --&gt; &lt;img ... /&gt;
  2. Prometheus 安装与配置
  3. HTML- 锚点实例
  4. leetcode.图.785判断二分图-Java
  5. HDU 4366 Successor( DFS序+ 线段树 )
  6. cygwin的用途
  7. asp.net core 使用中间件拦截请求和返回数据,并对数据进行加密解密。
  8. PHP多选测试练习
  9. Linux系统分辨率设置
  10. Codeforces 1195E. OpenStreetMap (单调队列)