zoukankan      html  css  js  c++  java
  • BZOJ4347: [POI2016]Nim z utrudnieniem

    BZOJ4347: [POI2016]Nim z utrudnieniem

    https://lydsy.com/JudgeOnline/problem.php?id=4347

    分析:

    • (f[i][j][k])表示前(i)堆石子选出(nd+k)堆使得异或和为(j)的方案数。
    • 那么这个直接转移是(O(n^2d))的。
    • 注意到(m)特别小。
    • 把石子按(a_i)排序之后处理即可,时间复杂度((md))
    • 这题卡空间,不能用滚动数组。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    using namespace std;
    #define N 500050
    #define M 1050050
    #define mod 1000000007
    typedef long long ll;
    int n,a[N],d;
    int f[M][10],g[M],Lg[M],h[M];
    void upd(int &x,int y) {
    	x=x+y; if(x>=mod) x-=mod;
    }
    char buf[100000],*p1,*p2;
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,10000,stdin),p1==p2)?EOF:*p1++)
    int rd() {
    	int x=0; char s=nc();
    	while(s<'0') s=nc();
    	while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc();
    	return x;
    }
    int main() {
    	n=rd(), d=rd();
    	int i,sum=0,mx=0,j,k;
    	for(i=1;i<=n;i++) a[i]=rd(),sum^=a[i],mx=max(mx,a[i]);
    	sort(a+1,a+n+1);
    	for(Lg[0]=-1,i=1;i<=mx;i++) Lg[i]=Lg[i>>1]+1;
    	f[0][0]=1;
    	for(i=0;i<n;i++) {
    		int len=1<<(Lg[a[i]]+1),t=a[i+1];
    		for(j=0;j<len;j++) h[j]=f[j][d-1];
    		for(k=d-2;k>=0;k--) {
    			for(j=0;j<len;j++) g[j]=f[j][k];
    			for(j=0;j<len;j++) {
    				upd(f[j^t][k+1],g[j]);
    			}
    		}
    		for(j=0;j<len;j++) {
    			upd(f[j^t][0],h[j]);
    		}
    	}
    	if(n%d==0) f[sum][0]--;
    	printf("%d
    ",(f[sum][0]+mod)%mod);
    }
    
  • 相关阅读:
    hdu4911 简单树状数组
    hdu4911 简单树状数组
    hdu4912 LCA+贪心
    hdu4912 LCA+贪心
    hdu4907 水dp 或者set
    hdu4907 水dp 或者set
    hdu4908 中位数子串
    hdu4908 中位数子串
    hdu4909 状态压缩(偶数字符子串)
    hdu4909 状态压缩(偶数字符子串)
  • 原文地址:https://www.cnblogs.com/suika/p/10229781.html
Copyright © 2011-2022 走看看