码迷,mamicode.com
首页 > 其他好文 > 详细

P4876 近似排列计数

时间:2017-10-04 14:17:49      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:题目   style   main   计算   names   using   位置   tab   计数   

时间限制:1s

内存限制:256MB

【问题述】

    对于一个1~n的排列,如果满足第i个数|ai-i|<=k,则称该排列为K-近似排列。

    现在排列的若干位置已经确定,你需要计算剩下的数有多少种排列方法使得形成的排列是K-近似排列。

【输入】

输入文件名为count.in。

第一行一个数T(<=10),表示数据组数

对于每一组数据:

第一行三个数n,m,k,分别表示排列长度、已确定位置的个数和近似参数K

         接下来m行,每行两个数x、y,表示已经确定第x个数是y

【输出】

输出文件名为count.out。

对于每组数据输出一行,包含一个数,表示方法个数(对1,000,000,007取模)

 

【输入输出样例】

count.in

count.out

1

4 1 1

2 3

1

 

【数据说明】

对于30%的数据,1<=n,m<=10,k<=2

对于50%的数据,1<=n,m<=20,k<=2

对于70%的数据,1<=n<=100000,m<=100,k<=2

对于100%的数据,1<=n<=10^9,m<=100,k<=2

坑啊,题目给的样例不对,他写的是2,其实是1.!

小暴力50分


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
using namespace std;
int n,m,k,t;
int a[100009];
bool vis[100009];
long long ans;
void dfs(int x)
{        
    if(x==n+1)
    {
        ans++;
        return ;
    }
    if(a[x])    dfs(x+1);
    else 
    {
        if(x>=3)
        if(!vis[x-k])
        {
            vis[x-k]=1;
            dfs(x+1);
            vis[x-k]=0;
            return ;
        }
        
        for(int i=max(x-k,1);i<=min(x+k,n);i++)
        if(!vis[i])
        {
            vis[i]=1;
            dfs(x+1);
            vis[i]=0;
        }
    }
    return ;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++) a[i]=0,vis[i]=0;
        ans=0;        
        for(int i=1,x,y;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            a[x]=y;vis[y]=1;
        }
        dfs(1);
        printf("%lld\n",ans);
    }
    return 0;
}

 

P4876 近似排列计数

标签:题目   style   main   计算   names   using   位置   tab   计数   

原文地址:http://www.cnblogs.com/CLGYPYJ/p/7625296.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!