zoukankan      html  css  js  c++  java
  • 画山 paint

    画山 paint

    有一张大小为n*m的白纸,小R想在纸上画一片绵延的群山。

    为了描述方便,我们将纸张表示在坐标系上,四个顶点的坐标分别为(0,0),(n,0),(0,m),(n,m)。

    小R有一只神奇的画笔,能画p种不同的线段,每种线段用两个参数a,b表示,若画笔停留的位置为(x,y),则能画一条从(x,y)到(x+a,y+b)的线段,然后画笔停留在(x+a,y+b),每种线段能画任意次。

    小R需要从(0,0)开始,在(n,0)结束,在不超过纸张大小的范围内(可以在边界上)画一片绵延的群山。求一共有多少种本质不同的山形(亦即我们不认为画两次(1,1)和画一次(2,2)有任何区别)。由于结果可能会很大,你只需输出对1,000,000,007取模后的值。

    【数据范围】

    对于40%的数据,n,m,p≤10

    对于100%的数据,n,m,p≤100,1≤ai≤10,-10≤bi≤10


    这数据范围看着就很佛系

    先把斜率相同的画笔归类,处理处该画笔可以画多少不同的长度。

    可以令f[x][y][i]表示画到(x,y),最后一次用的笔种类是i的方案数

    再记s[x][y]表示画到(x,y)总方案数

    转移的时候取两个差值,避免同一种笔画两次就行。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<queue>
     8 #define mod 1000000007
     9 #define ll long long 
    10 using namespace std;
    11 int n,m,p,flag[102][102],tot,sum[102],id[25][25];
    12 ll f[102][102][102],S[102][102];
    13 struct node{
    14     int x,y;double k;
    15 }s[105],a[102];
    16 bool cmp(node a,node b){return a.k<b.k;}
    17 bool pd(int x,int y){
    18     if(x>=0&&x<=n&&y>=0&&y<=m)return 1;
    19     return 0;
    20 }
    21 int gcd(int x,int y){
    22     if(!y)return x;
    23     return gcd(y,x%y);
    24 }
    25 int main(){
    26     cin>>n>>m>>p;
    27     for(int i=1;i<=p;i++){
    28         scanf("%d%d",&s[i].x,&s[i].y);
    29         s[i].k=(double)s[i].y/s[i].x; 
    30     }
    31     for(int i=1;i<=p;i++){
    32         int g=gcd(s[i].x,abs(s[i].y));
    33         s[i].x/=g;s[i].y/=g;
    34         int nx=s[i].x+10,ny=s[i].y+10;
    35         if(!id[nx][ny])id[nx][ny]=++tot,a[tot].x=s[i].x,a[tot].y=s[i].y;
    36         int t=id[nx][ny];
    37         flag[t][0]=1;
    38         for (int l=g;l*s[i].x<=n;l++)
    39             flag[t][l]|=flag[t][l-g];
    40     }
    41 
    42     S[0][0]=1;
    43     for(int x=0;x<=n;x++)
    44     for(int y=0;y<=m;y++){
    45         for(int i=1;i<=tot;i++){
    46             for(int j=1;j<=n;j++){
    47                 int nx=x-a[i].x*j,ny=y-a[i].y*j;
    48                 if(nx>=0 && nx<=n && ny>=0 && ny<=m){
    49                 //cxout<<nx<<' '<<ny<<' '<<f[x][y][i]<<endl;
    50                 if(flag[i][j])f[x][y][i]=(f[x][y][i]+S[nx][ny]-f[nx][ny][i])%mod;
    51                 }
    52                 else break;
    53             }
    54             S[x][y]+=f[x][y][i];S[x][y]%=mod;
    55         }
    56         
    57     }
    58     cout<<S[n][0]<<endl;
    59     return 0;
    60 }
    View Code
  • 相关阅读:
    bzoj 1013: [JSOI2008]球形空间产生器sphere
    bzoj 1012: [JSOI2008]最大数maxnumber
    bzoj 1010: [HNOI2008]玩具装箱toy
    bzoj 1008: [HNOI2008]越狱
    bzoj 1007: [HNOI2008]水平可见直线
    UVa12105 越大越好
    POJ
    最优点配对问题(紫书)
    Ned 的难题
    UVA
  • 原文地址:https://www.cnblogs.com/liankewei/p/11157482.html
Copyright © 2011-2022 走看看