NOIP2009题解

T1:潜伏者

题目大意:给出一段密文和破译后的明文,一个字母对应一个密文字母,要求破译一段密文,如果有矛盾或有未出现密文无法破译输出failed,否则输出明文。

思路:纯模拟题

T2:Hankson的趣味题

题目大意:给出a0,a1,b0,b1求满足条件的x的个数;

条件:gcd(x,a0)=a1;x,b0最小公倍数为b1;

思路:分解质因数,假设对于一个质因数y,a0含有a0c个y,a1含有a1c个y,b0含有b0c个y,b1含有b1c个y。

那么不难得到,如果a0c<a1c,那么就无解;如果a0c=a1c,那么x至少含有a1c个y;如果a0c>a1c,那么x只可能含有a1c个y。

同理,如果b1c<b0c,那么就无解;如果b1c=b0c,那么x至多含有b1c个y;如果b1c>b0c,那么x只可能含有b1c个y。

由此,可以求出对于每一个质数,x可能含有几个它,并求出一共有多少种选择方式。然后根据乘法原理,将每一个质数的选择方案数乘起来,就得到了答案。

----------------------------------------------------------

2017.5.6补充题解:

  今天又做了一遍,然后对上面自己的做法一脸懵逼,估计是之前就没看懂吧然后贴了题解???

  然后就各种焦虑,物色到了一个超级有道理的题解:

  可以证明gcd(x/a1,a0/a1)==1,显然如果不等于1,则gcd(x,a0)<a1;

  然后可以证明gcd(b1/x,b1/b0)==1,显然如果不等于1,则lcm(x,b0)<b1;

  这样的话,显然就可以枚举b1的所有因数,sqrt(b1),加上gcd复杂度是logb1,所以单组数据复杂度是sqrt(b1)*log2(b1).

T3:最优贸易

题目大意:n个城市m条路,有单向和双向,水晶球在每个城市价格不同,求从城市1到n能获得的最大差价,每个城市可走多次。

思路,边数太多,所以用SPFA,正向做一次取最小,把路都反过来从n倒做一次取最大。在枚举i得到max(max[i]-min[i]);

AC代码:

#include <iostream>

using namespace std;

int num[];

int map[],nxt[];

int las;

int head[];

int map2[],nxt2[];

int las2;

int head2[];

void adad(int a,int b)

{

    map[las]=b;

    nxt[las]=head[a];

    head[a]=las++;

}

void adad2(int a,int b)

{

    map2[las2]=b;

    nxt2[las2]=head2[a];

    head2[a]=las2++;

}

#define Q_MAX 100000

int used[];

int queue[Q_MAX];

int h,r;

void enq(int k)

{

    if (used[k])

        return;

    used[k]=;

    queue[r]=k;

    r=(r+)%Q_MAX;

}

int exq()

{

    int t;

    t=queue[h];

    used[t]=;

    h=(h+)%Q_MAX;

    return t;

}

int minn[];

int maxn[];

int main()

{

    int i,j;

    int n,m;

    int a,b,c;

    cin >> n >> m;

    for (i=;i<n;i++)

         {

        head[i]=head2[i]=-;

        maxn[i]=-;

        minn[i]=0xFFFFFFF;

        cin >> num[i];

    }

    for (i=;i<m;i++)

         {

        cin >> a >> b >> c;

        a--,b--;

        if (c==)

                   {

            adad(a,b);

            adad(b,a);

            adad2(a,b);

            adad2(b,a);

        }

                   else

                   {

            adad(a,b);

            adad2(b,a);

        }

    }

    minn[]=num[];

    enq();

    while (h!=r)

         {

        i=exq();

        for (a=head[i];a!=-;a=nxt[a])

                   {

            j=map[a];

            if (minn[j]>minn[i])

                            {

                minn[j]=minn[i];

                enq(j);

            }

            if (minn[j]>num[j])

                            {

                minn[j]=num[j];

                enq(j);

            }

        }

    }

    maxn[n-]=num[n-];

    enq(n-);

    while (h!=r)

         {

        i=exq();

        for (a=head2[i];a!=-;a=nxt2[a])

                   {

            j=map2[a];

            if (maxn[j]<maxn[i])

                            {

                maxn[j]=maxn[i];

                enq(j);

            }

            if (maxn[j]<num[j])

                            {

                maxn[j]=num[j];

                enq(j);

            }

        }

    }

    for (i=a=;i<n;i++)

        if (a<maxn[i]-minn[i])

            a=maxn[i]-minn[i];

    cout << a << "\n";

    return ;

}

T4:靶形数独

题目大意:解一个多解数独,从内向外分数不同,求分数最大的解法。

思路:解法肯定还是一样的,dfs。然后比较分数大小输出最大的。

然而这样会超时,codevs上可以过但是最慢的点用了2400多ms,时限4秒。

借鉴了一下某位神牛,用位运算加快运算速度(难写啊啊啊),试了一下还是能过的。

AC代码:

#include<iostream>

#include<cmath>

using namespace std;

int h[]={},hs[]={},zs[]={},xj[][]={},hq[]={};

int ans=-,st[],a[][];

void make()

{

         int i,j,sum=;

         for (i=;i<;i++)

         {

                   for (j=i;j<-i;j++)

                            sum+=(a[i][j]+a[-i][j])*(+i);

                   for (j=i+;j<-i;j++)

                            sum+=(a[j][i]+a[j][-i])*(+i);

         }

         sum+=a[][]*;  

         if (sum>ans)

                   ans=sum;

}

void dfs(int k)

{

         if (k==)

                   make();

         else

         {

                   int x,y,j,pos,p,i=st[k];

                   x=-h[i];

                   y=x&-x;

                   h[i]|=y;

                   j=(int)log2(y)+;

                   pos=-(hs[i]|zs[j]|xj[(i-)/][(j-)/]);

                   while (pos>)

                   {

                            p=pos&-pos;

                            pos-=p;

                            a[i][j]=(int)log2(p)+;

                            hs[i]|=p;

                            zs[j]|=p;

                            xj[(i-)/][(j-)/]|=p;

                            if (x==y)

                                     dfs(k+);

                            else

                                     dfs(k);

                            hs[i]-=p;

                            zs[j]-=p;

                            xj[(i-)/][(j-)/]-=p;

                   }

                   h[i]-=y;

         }

}

int main()

{

         int i,j,p0;

         for (i=;i<;i++)

                   for (j=;j<;j++)

                   {

                            cin >> a[i][j];

                            if (a[i][j]>)

                            {

                                     h[i]|=<<(j-);

                                     p0=<<(a[i][j]-);

                                     if (((hs[i]&p0)!=)||((zs[j]&p0)!=)||((xj[(i-)/][(j-)/]&p0)!=))

                                     {

                                               cout << "-1\n";

                                               return ;

                                     }

                                     hs[i]|=p0;

                                     zs[j]|=p0;

                                     xj[(i-)/][(j-)/]|=p0;

                            }

                            else

                                     hq[i]++;

                   }

         for (i=;i<;i++)

                   st[i]=i;

         for (i=;i<;i++)

                   for (j=i+;j<;j++)

                            if (hq[st[i]]>hq[st[j]])

                            {

                                     st[i]^=st[j];

                                     st[j]^=st[i];

                                     st[i]^=st[j];

                            }

         i=;

         while (hq[st[i]]==)

                   i++;

    dfs(i);

         cout << ans << "\n";

         return ;

}

noip2009提高组题解的更多相关文章

  1. noip2010提高组题解

    NOIP2010提高组题解 T1:机器翻译 题目大意:顺序输入n个数,有一个队列容量为m,遇到未出现元素入队,求入队次数. AC做法:直接开1000的队列模拟过程. T2:乌龟棋 题目大意:有长度为n ...

  2. NOIP 2014 提高组 题解

    NOIP 2014 提高组 题解 No 1. 生活大爆炸版石头剪刀布 http://www.luogu.org/problem/show?pid=1328 这是道大水题,我都在想怎么会有人错了,没算法 ...

  3. NOIP 2001 提高组 题解

    NOIP 2001 提高组 题解 No 1. 一元三次方程求解 https://vijos.org/p/1116 看见有人认真推导了求解公式,然后猥琐暴力过的同学们在一边偷笑~~~ 数据小 暴力枚举即 ...

  4. NOIP 2000 提高组 题解

    NOIP2000 提高组 题解 No 1. 进制转换 https://www.rqnoj.cn/problem/295 水题 对于n和基数r, 每次用n mod r, 把余数按照逆序排列 注意 mod ...

  5. 【NOIP2018】提高组题解

    [NOIP2018]提高组题解 其实就是把写过的打个包而已 道路铺设 货币系统 赛道修建 旅行 咕咕咕 咕咕咕

  6. 洛谷 P1073 最优贸易 & [NOIP2009提高组](反向最短路)

    传送门 解题思路 很长的题,实际上在一个有向图(点有点权)中求一个从起点1到终点n的路径,使得这条路径上点权最大的点与点权最小的点的差值最大(要求必须从点权较小的点能够走到点权较大的点). ——最短路 ...

  7. [NOIP2009] 提高组 洛谷P1073 最优贸易

    题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路 ...

  8. [NOIP2009] 提高组 洛谷P1071 潜伏者

    题目描述 R 国和 S 国正陷入战火之中,双方都互派间谍,潜入对方内部,伺机行动.历尽艰险后,潜伏于 S 国的 R 国间谍小 C 终于摸清了 S 国军用密码的编码规则: 1. S 国军方内部欲发送的原 ...

  9. [NOIP2009] 提高组 洛谷P1074 靶形数独

    题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了他最近发明的 ...

随机推荐

  1. 设置ulimit值(Linux文件句柄数量)永久生效

    Linux 默认打开文件数linux 默认打开文件数为1024个,通过ulimit -a 可以查看open files修改这个限制可以使用ulimt -SHn 65536永久生效需要进行下面设置:1. ...

  2. Linux进程内存分析pmap命令(转)

    名称:       pmap - report memory map of a process(查看进程的内存映像信息)用法       pmap [ -x | -d ] [ -q ] pids... ...

  3. ibatis CDATA

    在使用ibatis时,经常需要配置待执行的sql语句.使用过ibatis的朋友都知道,无可避免的都会碰到一些不兼容.冲突的字符,多数人也都知道用<![CDATA[   ]]>标记避免Sql ...

  4. Top 6 Programming Languages for Mobile App Development

    Mobile application development industry in the last five years have multiplied in leaps and bounds, ...

  5. __VA_ARGS__用法(转)

    自定义调试信息的输出 调试信息的输出方法有很多种,  例如直接用printf,  或者出错时使用perror, fprintf等将信息直接打印到终端上, 在Qt上面一般使用qDebug,而守护进程则一 ...

  6. PLSQL_基础系列11_递归和层次查询CONNECT BY(案例)

    2015-05-31 Created By BaoXinjian

  7. Idea KeyGen

    import java.math.BigInteger; import java.util.Date; import java.util.Random; import java.util.Scanne ...

  8. STM32的串口

    一:2个状态位_itstatus与_flagstatus的区别: _flagstatus:只是读状态标志,不管中断是否使能或发生.例如使用查询方式发送数据就需要读改状态位. _itstatus:和中断 ...

  9. vs2015-Azure Mobile Service

    /App_Data /App_Start/ WebApiConfig.cs using System; using System.Collections.Generic; using System.C ...

  10. jdk与jre的区别

    很多程序员已经干了一段时间java了依然不明白jdk与jre的区别.JDK就是Java Development Kit.简单的说JDK是面向开发人员使用的SDK,它提供了Java的开发环境和运行环境. ...