【CQ】2016联合考试 电路图A

这里写图片描述

不想吐槽清华某人出的题了,但不看第三题那个987行的标程,前两题还能做,此题分析在task函数中
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<vector>
#include<cmath>
#include<cstring>
#define maxn 2005
#define mod 1000000007
using namespace std;
typedef long long lint;
int n,m,sz_p;
lint ans,ans2,t1,t2;
bool is_prime[100000005];
vector<int>p,e;

void prime_task(lint x)
{
    memset(is_prime,1,sizeof(is_prime));

    for(int i=2;i*i<=x;i++) if(is_prime[i])
    for(int j=i;j*i<=x;j++) is_prime[i*j]=0;

    for(int i=2;i<=x;i++) if(is_prime[i])
    {
        p.push_back(i);
        e.push_back(0);
    }
    sz_p=p.size();
}

void break_into(int x,int d)
{
    if(x==1) return;
    for(int i=0;p[i]<=x&&i<sz_p;i++)
    {
        lint t=0,tt=p[i];
        while(x>=tt)
        {
            t+=x/tt;
            tt*=p[i];
        }
        e[i]+=d*t;
    }
}

lint C(int a,int b)
{
    for(int i=0;i<sz_p;i++) e[i]=0;

    break_into(a,1);
    break_into(a-b,-1);
    break_into(b,-1);

    lint t=1;
    for(int i=0;i<sz_p;i++)
    for(int j=1;j<=e[i];j++) t=(t*p[i])%mod;
    return t;
}

void task1()
{
    //分析可知n个元件(n>=4),需要转向n次,其中需要逆时针转m=(n-4)/2次
    //如n=6时,m=1,rrrlrr为一种方案 
    //在n次转向中选m个空位填l的方案数就是第一问的答案
    ans=C(n,m);
    cout<<ans<<endl;
}

void task2()
{
    //仍然是组合数的算法
    //对于n-m次R和m次的L
    //手动画出的美观电路图是一个有直边有阶梯的图形,一定不能有连续的两次L

               __________ 
             _|        _| 
     -> 直边 |        _|      <-阶梯 
            |      _|   
            |_____|         这个图极为美观 

    t1=C(n-m-1,m);  //电源在凸多边形的直边上:存在r------r(以r和r结尾),中间有n-m-1个空,填m个l 
    t2=C(n-m-1,m-1);//电源在阶梯上,则存在l---r或r---l,中间有n-m-1个空,填m-1个l的方案数 
    t2=(t2+t2)%mod; //l和r分别作为头和尾是两种情况 
    ans2=(t1+t2)%mod;
    cout<<ans2<<endl;
}

int main()
{
    //freopen("A.in","r",stdin);
    //freopen("A.out","w",stdout); 
    scanf("%d",&n);
    m=(n-4)/2;
    prime_task(2*n);
    task1();
    task2(); 
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_35546348/article/details/53177253