noip模拟题11.12

T1 A

这里写图片描述这里写图片描述
pdf是图片,我也懒得打字了,直接复制。
此题先写个暴力发现,数据是卡特兰数,那么递推就行了。但有个问题,由于递推式中有除法,中途%数可能会出现差错,所以直接推貌似和暴力分一样…
数论蒟蒻的我怎么也不会想到这个性质:( a / b ) % p = ( a * b’ ) % p。其中 b’ 是 b 的逆元。
代码:

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
#define mod 1000000009
using namespace std;
long long f[1000005];
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void gcd(int a,int b,int &d,int &x,int &y)
{
    if(!b){d=a;x=1;y=0;}
    else{gcd(b,a%b,d,y,x);y-=x*(a/b);}
}
long long count(int a,int b)
{
    int d,x,y;
    gcd(a,b,d,x,y);
    return (x+b)%b;
}
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    int T=read();
    f[1]=1;
    for(int i=2;i<=1000000;i++)
        f[i]=((f[i-1]*count(i+1,mod))%mod*(i*4-2))%mod;
    while(T--)
    {
        int n=read();
        printf(AUTO,f[n>>1]%mod);
        printf("\n");
    }
    return 0;
}

T2

这里写图片描述
简单贪心。预处理前缀和,记一个变量tmp=0。枚举 i ,如果a[i]<0,入优先队列。如果此时sum[i]-tmp+h<0,tmp+=q.top,循环,直到sum[i]-tmp+h>=0。
代码:

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
long long a[1005],sum[1005];
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int main()
{
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
    int n=read(),m=read();
    for(int i=1;i<=n;i++)
    {
        scanf(AUTO,&a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    while(m--)
    {
        priority_queue<long long>q;
        long long h,tmp=0,ans=0;
        scanf(AUTO,&h);
        for(int i=1;i<=n;i++)
        {
            if(a[i]<0)q.push(-a[i]);
            if(h+sum[i]-tmp<0)
                while(h+sum[i]-tmp<0)
                {
                    tmp+=-q.top();q.pop();ans++;
                }
        }
        printf(AUTO,ans);printf("\n");
    }
    return 0;
}

T3 C

【问题描述】

小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低。但普通的数独对他们来说都过于简单了,于是他们向Z博士请教,Z博士拿出了他最近发明的“靶形数独”,作为这两个孩子比试的题目。
靶形数独的方格同普通数独一样,在9格宽×9格高的大九宫格中有9个3格宽×3格高的小九宫格(用粗黑色线隔开的)。在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入1到9的数字。每个数字在每个小九宫格内不能重复出现,每个数字在每行、每列也不能重复出现。但靶形数独有一点和普通数独不同,即每一个方格都有一个分值,而且如同一个靶子一样,离中心越近则分值越高。(如图)
这里写图片描述
上图具体的分值分布是:最里面一格(黄色区域)为10分,黄色区域外面的一圈(红色区域)每个格子为9分,再外面一圈(蓝色区域)每个格子为8分,蓝色区域外面一圈(棕色区域)每个格子为7分,最外面一圈(白色区域)每个格子为6分,如上图所示。比赛的要求是:每个人必须完成一个给定的数独(每个给定数独有可能有不同的填法),而且要争取更高的总分数。而这个总分数即每个方格上的分值和完成这个数独时填在相应格上的数字的乘积的总和。如图,在以下这个已经填完数字的靶形数独游戏中,总分为2829。游戏规定,将以总分数的高低决出胜负。
这里写图片描述
由于求胜心切,小城找到了善于编程的你,让你帮他求出,对于给定的靶形数独,能够得到的最高分数。

【输入】

输入文件名为c.in。
一共9行,每行9个整数(每个数都在0—9的范围内),表示一个尚未填满的数独方格,未填满的空格用“0”表示。每两个数字之间用一个空格隔开。

【输出】

输出文件c.out共1行。
输出可以得到的靶形数独的最高分数。如果这个数独无解,则输出整数-1。

【输入输出样例1】

c.in
7 0 0 9 0 0 0 0 1
1 0 0 0 0 5 9 0 0
0 0 0 2 0 0 0 8 0
0 0 5 0 2 0 0 0 3
0 0 0 0 0 0 6 4 8
4 1 3 0 0 0 0 0 0
0 0 7 0 0 2 0 9 0
2 0 1 0 6 0 8 0 4
0 8 0 5 0 4 0 1 2
c.out
2829

【输入输出样例2】

c.in
0 0 0 7 0 2 4 5 3
9 0 0 0 0 8 0 0 0
7 4 0 0 0 5 0 1 0
1 9 5 0 8 0 0 0 0
0 7 0 0 0 0 0 2 5
0 3 0 5 7 9 1 0 8
0 0 0 6 0 1 0 0 0
0 6 0 9 0 0 0 0 1
0 0 0 0 0 0 0 0 6
c.out
2852

【数据范围】

40%的数据,数独中非0数的个数不少于30。
80%的数据,数独中非0数的个数不少于26。
100%的数据,数独中非0数的个数不少于24。

noip2009原题,记三个数组,表示第几行第几个数是否用过,第几列第几个数是否用过,第几块第几个数是否用过,然后暴力枚举+卡时,vj上只wa了一个…学校电脑wa两个。
代码:

#include<ctime>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
int ans=-1,g[10][10],map[10][10],belong[10][10],toto;
int vishang[10][10],vislie[10][10],vistot[10][10];
int vjudge[9][9]={{6,6,6,6,6,6,6,6,6},
                {6,7,7,7,7,7,7,7,6},
                {6,7,8,8,8,8,8,7,6},
                {6,7,8,9,9,9,8,7,6},
                {6,7,8,9,10,9,8,7,6},
                {6,7,8,9,9,9,8,7,6},
                {6,7,8,8,8,8,8,7,6},
                {6,7,7,7,7,7,7,7,6},
                {6,6,6,6,6,6,6,6,6}};
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline int count()
{
    int tot=0;
    for(int i=1;i<=9;++i)
        for(int j=1;j<=9;++j)
            tot+=vjudge[i-1][j-1]*g[i][j];
    return tot;
}
inline void dfs(int x,int y)
{
    toto++;
    if(toto>30000)
    {
        if(clock()>980)
        {
            printf("%d",ans);
            exit(0);
        }
    }
    if(x==10)
    {
        ans=max(ans,count());
        return ;
    }
    if(map[x][y])
    {
        if(y<9)
            dfs(x,y+1);
        else dfs(x+1,1);
    }
    else
    {
        for(int i=9;i>=1;--i)//从9->1更优
            if(!vishang[x][i]&&!vislie[y][i]&&!vistot[belong[x][y]][i])
            {
                g[x][y]=i;
                vishang[x][i]=1;vislie[y][i]=1;
                vistot[belong[x][y]][i]=1;
                if(y<9)
                    dfs(x,y+1);
                else dfs(x+1,1);
                g[x][y]=0;vishang[x][i]=0;vislie[y][i]=0;
                vistot[belong[x][y]][i]=0;
            }
    }
}
inline void init()
{
    for(int i=1;i<=9;++i)
        for(int j=1;j<=9;++j)
        {
            if(i<=3&&j<=3)belong[i][j]=1;
            else if(j>=4&&j<=6&&i<=3)belong[i][j]=2;
            else if(j>=7&&j<=9&&i<=3)belong[i][j]=3;
            else if(j<=3&&i>=4&&i<=6)belong[i][j]=4;
            else if(j<=6&&j>=4&&i>=4&&i<=6)belong[i][j]=5;
            else if(j<=9&&j>=7&&i>=4&&i<=6)belong[i][j]=6;
            else if(j<=3&&i>=7&&i<=9)belong[i][j]=7;
            else if(j<=6&&j>=4&&i>=7&&i<=9)belong[i][j]=8;
            else if(j<=9&&j>=7&&i>=7&&i<=9)belong[i][j]=9;
        }
    for(int i=1;i<=9;++i)
        for(int j=1;j<=9;++j)
        {
            map[i][j]=read();g[i][j]=map[i][j];
            if(map[i][j]!=0)
            {
                if(!vishang[i][map[i][j]])
                    if(!vislie[j][map[i][j]])
                        if(!vistot[belong[i][j]][map[i][j]])
                        {
                            vishang[i][map[i][j]]=1;
                            vislie[j][map[i][j]]=1;
                            vistot[belong[i][j]][map[i][j]]=1;
                            continue;
                        }
                printf("-1");
                exit(0);
            }
        }
}
int main()
{
    freopen("c.in","r",stdin);
    freopen("c.out","w",stdout);
    init();
    dfs(1,1);
    printf("%d",ans);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值