zoukankan      html  css  js  c++  java
  • jzojs 5384. 【NOIP2017提高A组模拟9.23】四维世界

    Description
    众所周知,我们常感受的世界是三维的。
    Polycarp突然对四维空间产生了兴趣,他想对四维空间进行一些研究。但是在此之前,他必须先对三维世界了解透彻。
    于是Polycarp决定从零维,也就是一个点,开始他的研究。我们把一个点放在三维空间中,Polycarp把这个点视为原点,并确定了三个正方向。他可以把这个点往三个方向之一拉伸一个单位,那么这个点就变为了一维的一条长度为一的线段。然后如果他把这条线段往另一方向拉伸一个单位,那么这条线就变为了二维的一个矩形。如果继续拉伸可能就会进入三维世界,也就是变为直四棱柱。
    Polycarp认为矩形、线段甚至点都可以看作某一维或某几维为丰的直四棱柱。
    现在Polycarp想演示把一个点一步一步拉伸为边长为n的正六面体的过程,但他缺失了m种形态的直四棱柱模具(Polycarp拥有其他的所有直四棱柱模具),他想知道共有多少种演示方案。
    Polycarp的演示过程需要每拉伸一个单位时对应形态的直四棱柱。
    因为方案数很大,所以输出答案对10^9+7的结果。

    Input
    从文件poly.in中读入数据。
    第一行两个整数n;m,分别表示直四棱柱的边长和他缺失的模具数量。
    接下来m行,第i行三个整数x; y; z,表示第i个缺失模具的长、宽、高。

    Output
    输出到文件poly.out中
    一个整数,即答案。

    Sample Input
    2 3
    1 0 1
    1 1 1
    0 2 0

    Sample Output
    36

    100%,n<=10^5,m<=5000

    不多说,直接暴力模拟即可。

    #include<cstdio>
    #include<algorithm>
    #define ll long long
    #define mo 1000000007
    using namespace std;
    struct node{int x,y,z;}a[5010];
    ll jc[300010],nyj[100010],f[5010];
    int n,m;
    
    inline int read()
    {
    	int x=0; char c=getchar();
    	while (c<'0' || c>'9') c=getchar();
    	while (c>='0' && c<='9') x=x*10+c-48,c=getchar();
    	return x;
    }
    
    ll ny(ll x)
    {
    	ll s=1,y=mo-2;
    	while (y)
    	{
    		if (y & 1) s=s*x%mo;
    		x=x*x%mo;y>>=1;
    	}
    	return s;
    }
    
    int cmp(node x,node y) {return x.x==y.x ? ((x.y==y.y) ? x.z<y.z:x.y<y.y):x.x<y.x;}
    
    ll doit(int x,int y,int z) {return jc[x+y+z]*nyj[x]%mo*nyj[y]%mo*nyj[z]%mo;}
    
    int main()
    {
    	freopen("poly.in","r",stdin);
    	freopen("poly.out","w",stdout);
    	jc[0]=jc[1]=1;for (int i=2;i<=300000;i++) jc[i]=jc[i-1]*i%mo;
    	nyj[100000]=ny(jc[100000]);
    	for (int i=99999;i>=0;i--) nyj[i]=nyj[i+1]*(i+1)%mo;
    	n=read(),m=read();
    	for (int i=1;i<=m;i++)
    		a[i].x=read(),a[i].y=read(),a[i].z=read();
    	a[++m]=(node){n,n,n};
    	sort(a+1,a+m+1,cmp);
    	for (int i=1;i<=m;i++)
    	{
    		f[i]=doit(a[i].x,a[i].y,a[i].z);
    		for (int j=1;j<i;j++)
    			if (a[i].y>=a[j].y && a[i].z>=a[j].z)
    				f[i]=(f[i]-f[j]*doit(a[i].x-a[j].x,a[i].y-a[j].y,a[i].z-a[j].z)+mo)%mo;
    	}
    	printf("%lld
    ",f[m]);
    	return 0;
    } 
    
    转载需注明出处。
  • 相关阅读:
    python基础6 迭代器 生成器
    Netty入门之客户端与服务端通信(二)
    Netty入门之HelloWorld
    Java并发之BlockingQueue的使用
    Java并发之Semaphore的使用
    Java并发之CyclicBarria的使用(二)
    Java并发之CyclicBarria的使用
    Java并发之CountDownLatch的使用
    MongoDB的下载与安装
    Hibernate5.2之反向工程
  • 原文地址:https://www.cnblogs.com/jz929/p/11817851.html
Copyright © 2011-2022 走看看