首页 > 其他 > 详细

BZOJ4197[NOI2005]寿司晚宴

时间:2017-01-07 22:24:37      阅读:286      评论:0      收藏:0      [点我收藏+]

Description

为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴。小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴。
在晚宴上,主办方为大家提供了 n?1 种不同的寿司,编号 1,2,3,…,n?1,其中第 i 种寿司的美味度为 i+1 (即寿司的美味度为从 2 到 n)。
现在小 G 和小 W 希望每人选一些寿司种类来品尝,他们规定一种品尝方案为不和谐的当且仅当:小 G 品尝的寿司种类中存在一种美味度为 x 的寿司,小 W 品尝的寿司中存在一种美味度为 y 的寿司,而 x 与 y 不互质。
现在小 G 和小 W 希望统计一共有多少种和谐的品尝寿司的方案(对给定的正整数 p 取模)。注意一个人可以不吃任何寿司。

Input

输入文件的第 1 行包含 2 个正整数 n,p,中间用单个空格隔开,表示共有 n 种寿司,最终和谐的方案数要对 p 取模。

Output

输出一行包含 1 个整数,表示所求的方案模 p 的结果。 

Sample Input

3 10000

Sample Output

9

HINT

2≤n≤500

0<p≤1000000000
 
题解:
两人拥有的寿司美味度的质因子数不能有重复,对于小于√500的质因子将其在G手中、在W手中、不在两人手中压缩成3进制状态j,用dp[j]储存方案数。
先预处理好美味度为小于√500的质数的寿司归属,在枚举其他寿司插入。
插入一个大于√500的质数寿司P时,同时考虑其倍数。新开一个数组dp2[0~2,j]表示该质因子不在二人手中、在G手中、在W手中时,状态为j的方案数
将P的倍数寿司插入,假设其为KP,通过三个数组转移。
注意转移时该质因子归属、小于√500质因子归属的变化(若K的某个质因子p已在对方手中,则不可拥有;若两人都不拥有,则可以拥有这个寿司,并更新状态;若p质因子已在自己手中,则可以拥有这个寿司)
转移方向:0——>1、2   1——>1   2——>2
用所有P的倍数插入并转移后,将dp2[1~2]数组转到dp数组中。
插入质因子都在√500以内的合数寿司时,用类似方法在DP数组中转移。
最后统计答案。
 
代码:
uses math;
const
  zs:array[1..8]of longint=(2,3,5,7,11,13,17,19);
var
  i,ii,j,jj,k,l,fl,n:longint;
  a:array[0..501]of int64;
  b:array[0..8]of int64;
  dp:array[0..7000]of int64;
  dp2:array[0..2,0..7000]of int64;
  ans,tj,mo:int64;
begin
  readln(n,mo);
  b[0]:=1; for i:=1 to 8 do b[i]:=b[i-1]*3;
  for i:=0 to b[8]-1 do dp[i]:=1;
  for i:=2 to n do
  if a[i]=0 then
  begin
    j:=i*2;
    while j<=n do
    begin
      if i>20 then a[j]:=2 else a[j]:=max(a[j],1);
      j:=j+i;
    end;
    if i>20 then
    begin
      for j:=0 to b[8]-1 do
      begin
        dp2[0,j]:=dp[j]; dp2[1,j]:=0; dp2[2,j]:=0;
      end;
      ii:=i; k:=1;
      while ii<=n do
      begin
        for jj:=1 to 2 do
        for j:=b[8]-1 downto 0 do
        if dp2[jj,j]>0 then
        begin
          tj:=j; fl:=0;
          for l:=1 to 8 do
          if k mod zs[l]=0 then
          begin
            if (tj div b[l-1])mod 3=3-jj then
            begin fl:=1; break; end else
            tj:=tj+(jj-(tj div b[l-1])mod 3)*b[l-1];
          end;
          if fl=0 then dp2[jj,tj]:=(dp2[jj,tj]+dp2[jj,j])mod mo;
        end;
        for j:=b[8]-1 downto 0 do
        begin
          for jj:=1 to 2 do
          begin
            tj:=j; fl:=0;
            for l:=1 to 8 do
            if k mod zs[l]=0 then
            begin
              if (tj div b[l-1])mod 3=3-jj then
              begin fl:=1; break; end else
              tj:=tj+(jj-(tj div b[l-1])mod 3)*b[l-1];
            end;
            if fl=0 then dp2[jj,tj]:=(dp2[jj,tj]+dp2[0,j])mod mo;
          end;
        end;
        ii:=ii+i; inc(k);
      end;
      for j:=0 to b[8]-1 do dp[j]:=(dp[j]+dp2[1,j]+dp2[2,j])mod mo;
    end;
  end else
  if a[i]=1 then
  begin
    for j:=b[8]-1 downto 0 do
    begin
      for jj:=1 to 2 do
      begin
        tj:=j; fl:=0;
        for l:=1 to 8 do
        if i mod zs[l]=0 then
        begin
          if (tj div b[l-1])mod 3=3-jj then
          begin fl:=1; break; end else
          tj:=tj+(jj-(tj div b[l-1])mod 3)*b[l-1];
        end;
        if fl=0 then dp[tj]:=(dp[tj]+dp[j])mod mo;
      end;
    end;
  end;
  for i:=0 to b[8]-1 do
  begin
    fl:=0;
    for l:=1 to 8 do
    if(zs[l]>n)and((i div b[l-1])mod 3<>0)then
    begin fl:=1; break; end;
    if fl=0 then ans:=(ans+dp[i])mod mo;
  end;
  writeln(ans);
end.

BZOJ4197[NOI2005]寿司晚宴

原文:http://www.cnblogs.com/GhostReach/p/6260348.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!