标题: 几道编程题
性别:男-离线 周瑜

栎阳侯谏议大夫

Rank: 16
组别 翰林学士
级别 征西将军
好贴 10
功绩 943
帖子 4716
编号 1808
注册 2003-11-3
家族 瓦岗寨


发表于 2010-5-29 02:32 资料 主页 文集 短消息 只看该作者
孝直的理解是正确的,无论是闭合且连接电源的开关,还是打开但有一半连接电源的开关,按下按钮后都会翻转。
如果要设计电路,那就是每个开关之前有一个翻转装置与按钮相连,开关前端一旦有电压,在按钮触发下翻转装置即可工作。

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

新上传了测试用例,各位可以用来测试自己的程序。如果文件读写困难,可以使用freopen重定向输入输出,不用修改源代码,继续使用scanf/cin/gets和printf/cout/puts来读写文件。

值得注意的是:

1.所有输入都满足限制条件,不必另行测试。
2.除非特殊说明,Case x:冒号之后有一个空格,然后才是输出结果。
3.大部分程序都在10秒内运行完成,如果程序运行超过1分钟,请改进程序。

[ 本帖最后由 周瑜 于 2010-5-28 16:46 编辑 ]


顶部
性别:未知-离线 Maxwell

代王
监管使
枢密直学士
山南西道节度使

Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27
柱国(正二品)
组别 诸侯
级别 征东将军
好贴 4
功绩 1845
帖子 5799
编号 622
注册 2004-7-7


发表于 2010-5-29 07:53 资料 文集 短消息 只看该作者


QUOTE:
原帖由 周瑜 于 2010-5-25 04:43 发表
01 链式开关

我的理解有问题吗,怎么感觉就是一个二进制进位?直接根据k输出各位的值就可以了。


顶部
性别:未知-离线 Maxwell

代王
监管使
枢密直学士
山南西道节度使

Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27
柱国(正二品)
组别 诸侯
级别 征东将军
好贴 4
功绩 1845
帖子 5799
编号 622
注册 2004-7-7


发表于 2010-5-29 10:07 资料 文集 短消息 只看该作者


QUOTE:
原帖由 周瑜 于 2010-5-25 04:45 发表
主题公园

算法上没仔细考虑,-O2在atom1.6上要20s,超时了,找个好机器试试。。。

#include <fstream>
#include <sstream>
#include <string>
#include <vector>

typedef std::vector<int> TIntVector;

__int64 Calc(TIntVector const& Group, int R, int k)
{
        __int64 Total = 0;
        TIntVector Step;
        TIntVector Count;
        int const GroupSize = Group.size();

        Step.resize(GroupSize);
        Count.resize(GroupSize);

        for (int i = 0; i < GroupSize; ++i)
        {
                int ItStep = 0;
                int ItCount = 0;

                for (int j = 0; j < GroupSize; ++j)
                {
                        int Sub = i + j;

                        if (Sub >= GroupSize)
                        {
                                Sub -= GroupSize;
                        }

                        if (ItCount + Group[Sub] <= k)
                        {
                                ++ItStep;
                                ItCount += Group[Sub];
                        }
                        else
                        {
                                break;
                        }
                }

                Step[i] = ItStep;
                Count[i] = ItCount;      
        }

        if (GroupSize == Step[0])
        {
                Total = Count[0] * static_cast<__int64>(R);
        }
        else
        {
                int Next = 0;

                for (int i = 0; i < R; ++i)
                {
                        Total += Count[Next];
                        Next += Step[Next];

                        if (Next >= GroupSize)
                        {
                                Next -= GroupSize;
                        }
                }
        }

        return Total;
}

int main()
{
        std::ifstream In("in.txt");
        std::ofstream Out("testout.txt");
        std::string Line;
        int T = 0;

        In >> T;

        for (int i = 0; i < T; ++i)
        {
                int R = 0;
                int k = 0;
                int N = 0;

                In >> R;
                In >> k;
                In >> N;

                int Value;
                TIntVector Group;

                for (int j = 0; j < N; ++j)
                {
                        In >> Value;
                        Group.push_back(Value);
                }

                __int64 Result = Calc(Group, R, k);

                Out << "Case #" << i + 1 << ": " << Result << std::endl;
        }

        return 0;
}

[ 本帖最后由 Maxwell 于 2010-5-29 11:01 编辑 ]
顶部
性别:未知-离线 Maxwell

代王
监管使
枢密直学士
山南西道节度使

Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27
柱国(正二品)
组别 诸侯
级别 征东将军
好贴 4
功绩 1845
帖子 5799
编号 622
注册 2004-7-7


发表于 2010-5-29 10:29 资料 文集 短消息 只看该作者
找了个2G的台式机试了试,11s。。。
顶部
性别:男-离线 周瑜

栎阳侯谏议大夫

Rank: 16
组别 翰林学士
级别 征西将军
好贴 10
功绩 943
帖子 4716
编号 1808
注册 2003-11-3
家族 瓦岗寨


发表于 2010-5-29 10:56 资料 主页 文集 短消息 只看该作者
第1题并不是输出第k位,而是要求最低k位全是1。

第3题程序有点小错误,最后的
if (k == Step[0])
应改为
if (GroupSize == Step[0])

11秒已经是比较好的成绩了,但是算法上还有可以改进的地方,比换好机器管用。由于 N 比 R 小的多,就连 N^2 都比 R 小,可以尝试使用O(N^2)甚至O(NlogN)的算法。当然,这需要一点数学推导。

[ 本帖最后由 周瑜 于 2010-5-28 23:07 编辑 ]
顶部
性别:未知-离线 Maxwell

代王
监管使
枢密直学士
山南西道节度使

Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27
柱国(正二品)
组别 诸侯
级别 征东将军
好贴 4
功绩 1845
帖子 5799
编号 622
注册 2004-7-7


发表于 2010-5-29 11:06 资料 文集 短消息 只看该作者


QUOTE:
原帖由 周瑜 于 2010-5-29 10:56 发表
第1题并不是输出第k位,而是要求最低k位全是1。

第3题程序有点小错误,最后的
if (k == Step)
应改为
if (GroupSize == Step)

11秒已经是比较好的成绩了,但是算法上还有可以改进的地方,比换好机器管 ...

第1题没仔细看题,以为Case #x是第x位了。。。O(1)的题太少见了。。。

嗯,是写错了,测试用例里正好没有能暴露问题的用例,结果没发现。。。还是不太适应这种竞赛性质的题,一堆单字母一会儿就晕了。。。
作为懒的借口,我强调符合要求就好回头仔细想想算法去

[ 本帖最后由 Maxwell 于 2010-5-29 11:12 编辑 ]
顶部
性别:未知-离线 Maxwell

代王
监管使
枢密直学士
山南西道节度使

Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27
柱国(正二品)
组别 诸侯
级别 征东将军
好贴 4
功绩 1845
帖子 5799
编号 622
注册 2004-7-7


发表于 2010-5-29 11:54 资料 文集 短消息 只看该作者


QUOTE:
原帖由 周瑜 于 2010-5-25 04:45 发表
主题公园

一个新算法,复杂度似乎小于3N。
其它部分不变,改为调用Calc2即可。程序一闪就结束了,无法计时。
这段程序一次写成,没有经过调试,不保证在任何情况下都正确。
-----------------
上面的复杂度有问题。。。中午出了门想起来不对了,这个算法第一个循环还是O(N^2)的,不过可以改进到O(N),大约是4N。代码不写了,只要缓存计算结果就可以。

__int64 Calc2(TIntVector const& Group, int R, int k)
{
        __int64 Total = 0;
        TIntVector Step;
        TIntVector Count;
        int const GroupSize = Group.size();

        Step.resize(GroupSize);
        Count.resize(GroupSize);

        for (int i = 0; i < GroupSize; ++i)
        {
                int ItStep = 0;
                int ItCount = 0;

                for (int j = 0; j < GroupSize; ++j)
                {
                        int Sub = i + j;

                        if (Sub >= GroupSize)
                        {
                                Sub -= GroupSize;
                        }

                        if (ItCount + Group[Sub] <= k)
                        {
                                ++ItStep;
                                ItCount += Group[Sub];
                        }
                        else
                        {
                                break;
                        }
                }

                Step[i] = ItStep;
                Count[i] = ItCount;
        }

        if (GroupSize == Step[0])
        {
                Total = Count[0] * static_cast<__int64>(R);
        }
        else
        {
                std::vector<__int64> PreCount;
                TIntVector PreR;
                TIntVector FlagN;
                int Next = 0;
                __int64 ItPreCount = 0;
                int ItPreR = 0;
                __int64 CycleCount = 0;
                int CycleR = 0;
                int TailNext = 0;
                bool Finish = true;

                PreCount.resize(GroupSize);
                PreR.resize(GroupSize);
                FlagN.resize(GroupSize);

                for (int i = 0; i < R; ++i)
                {
                        if (0 == FlagN[Next])
                        {
                                PreCount[Next] = Total;
                                PreR[Next] = i;
                                FlagN[Next] = 1;

                                Total += Count[Next];
                                Next += Step[Next];

                                if (Next >= GroupSize)
                                {
                                        Next -= GroupSize;
                                }
                        }
                        else
                        {
                                ItPreCount = PreCount[Next];
                                ItPreR = PreR[Next];
                                CycleCount = Total - ItPreCount;
                                CycleR = i - ItPreR;
                                TailNext = Next;
                                Finish = false;

                                break;
                        }
                }

                if (!Finish)
                {
                        __int64 Tail = 0;

                        for (int i = 0; i < ((R - ItPreR) % CycleR); ++i)
                        {
                                Tail += Count[TailNext];
                                TailNext += Step[TailNext];

                                if (TailNext >= GroupSize)
                                {
                                        TailNext -= GroupSize;
                                }
                        }

                        Total = ItPreCount + (R - ItPreR) / CycleR * static_cast<__int64>(CycleCount) + Tail;
                }
        }

        return Total;
}

[ 本帖最后由 Maxwell 于 2010-5-29 18:51 编辑 ]
顶部
性别:未知-离线 Maxwell

代王
监管使
枢密直学士
山南西道节度使

Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27
柱国(正二品)
组别 诸侯
级别 征东将军
好贴 4
功绩 1845
帖子 5799
编号 622
注册 2004-7-7


发表于 2010-5-29 18:46 资料 文集 短消息 只看该作者
上面的复杂度有问题。。。中午出了门想起来不对了,这个算法第一个循环还是O(N^2)的,不过可以改进到O(N),大约是4N。代码不写了,只要缓存计算结果就可以。
顶部
性别:男-离线 周瑜

栎阳侯谏议大夫

Rank: 16
组别 翰林学士
级别 征西将军
好贴 10
功绩 943
帖子 4716
编号 1808
注册 2003-11-3
家族 瓦岗寨


发表于 2010-5-30 02:54 资料 主页 文集 短消息 只看该作者
Maxwell这道题做的相当精彩,我只想到了使用二分法的O(NlogN)算法,却没想到类似双指针的O(N)算法。

看来即使题目中对N的限制提高到10^6或者10^7,也可以在很短时间内跑完了。
顶部
性别:未知-离线 Maxwell

代王
监管使
枢密直学士
山南西道节度使

Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27
柱国(正二品)
组别 诸侯
级别 征东将军
好贴 4
功绩 1845
帖子 5799
编号 622
注册 2004-7-7


发表于 2010-5-30 21:10 资料 文集 短消息 只看该作者


QUOTE:
原帖由 周瑜 于 2010-5-25 04:44 发表
02 太空观测

这个题如果我没理解错的话,主要难度在大数运算上,不过可以全用减法,程序简单。10^50不到180位,6个32位或者3个64位就够了。按说明看应该输入是降序排序的,不过示例输入值有从大到小的也有从小到大的,关键是没说是不是保证有序的,从示例也看不出来。
但是全用减法速度上不去,实现个除法比较好。

[ 本帖最后由 Maxwell 于 2010-5-30 21:27 编辑 ]
顶部
性别:男-离线 周瑜

栎阳侯谏议大夫

Rank: 16
组别 翰林学士
级别 征西将军
好贴 10
功绩 943
帖子 4716
编号 1808
注册 2003-11-3
家族 瓦岗寨


发表于 2010-5-31 03:13 资料 主页 文集 短消息 只看该作者
可能是我描述的不够清楚,已把题目改为“整数ti,表示过去的某次事件到现在的时间。”ti未必有序,也未必互不相等,但不会全相等。
顶部
性别:未知-离线 Maxwell

代王
监管使
枢密直学士
山南西道节度使

Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27
柱国(正二品)
组别 诸侯
级别 征东将军
好贴 4
功绩 1845
帖子 5799
编号 622
注册 2004-7-7


发表于 2010-5-31 12:12 资料 文集 短消息 只看该作者


QUOTE:
原帖由 周瑜 于 2010-5-31 03:13 发表
可能是我描述的不够清楚,已把题目改为“整数ti,表示过去的某次事件到现在的时间。”ti未必有序,也未必互不相等,但不会全相等。

后来想了一下,是否排序无所谓。不过两个相等的数值代表什么含义呢,是两次同时发生的事件还是重复数据?
顶部
性别:男-离线 周瑜

栎阳侯谏议大夫

Rank: 16
组别 翰林学士
级别 征西将军
好贴 10
功绩 943
帖子 4716
编号 1808
注册 2003-11-3
家族 瓦岗寨


发表于 2010-6-1 03:19 资料 主页 文集 短消息 只看该作者


QUOTE:
原帖由 Maxwell 于 2010-5-31 00:12 发表


后来想了一下,是否排序无所谓。不过两个相等的数值代表什么含义呢,是两次同时发生的事件还是重复数据?

是重复数据。其实这完全是干扰条件,只是手头拿到的数据就有重复的。
顶部
性别:未知-离线 Maxwell

代王
监管使
枢密直学士
山南西道节度使

Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27
柱国(正二品)
组别 诸侯
级别 征东将军
好贴 4
功绩 1845
帖子 5799
编号 622
注册 2004-7-7


发表于 2010-6-1 09:20 资料 文集 短消息 只看该作者


QUOTE:
原帖由 周瑜 于 2010-6-1 03:19 发表


是重复数据。其实这完全是干扰条件,只是手头拿到的数据就有重复的。

乍想一下,似乎除法挺复杂,但是只用减法差不多要O(ti)了。有空先写个减法的试试,除法的慢慢想。另外,第3题用怎么用二分法能给讲讲不?我没想出来对谁二分。
顶部
性别:男-离线 周瑜

栎阳侯谏议大夫

Rank: 16
组别 翰林学士
级别 征西将军
好贴 10
功绩 943
帖子 4716
编号 1808
注册 2003-11-3
家族 瓦岗寨


发表于 2010-6-1 10:47 资料 主页 文集 短消息 只看该作者
把 Group 数组复制一遍,附在原数组后面,即:
Group[N...2N-1] = Group[0...N-1]

定义 S[i] 为 Group 数组前 i 项之和,则 S 为递增数组
S[0] = 0
S[i] = S[i-1] + Group[i-1]

计算以每组起始登车时可装载的最后一组时,可在 S[i] 到 S[i+N] 之间使用二分法,使用 upper_bound 函数找到第一个大于 S[i]+k 的,指针减一即为最后上车的一组。

其实还是双指针的方法好,只遍历一次。两个指针一个指向起始位置,一个指向截止位置,每次起始位置后移1,截止位置不动或者后移若干。然后移动时很容易算出实际上车人数。

[color=Silver][[i] 本帖最后由 周瑜 于 2010-6-1 08:01 编辑 [/i]][/color]
顶部
性别:未知-离线 Maxwell

代王
监管使
枢密直学士
山南西道节度使

Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27
柱国(正二品)
组别 诸侯
级别 征东将军
好贴 4
功绩 1845
帖子 5799
编号 622
注册 2004-7-7


发表于 2010-6-3 18:44 资料 文集 短消息 只看该作者


QUOTE:
原帖由 周瑜 于 2010-5-25 04:44 发表
02 太空观测

尝试写了一个大数类,只实现了减法,发现效率实在太低,除法没时间写了。下面的代码是gcc+gmp写的,恐怕不是出题的原意了。

#include <fstream>
#include <string>
#include <vector>
#include <gmp.h>
#include <gmpxx.h>


typedef std::vector<mpz_class> TMpzVector;

mpz_class Calc1(TMpzVector const& Data)
{
        mpz_class MinTime = Data[0];
        mpz_class MinGcd = 0;
        size_t const DataLen = Data.size();

        for (size_t i = 1; i < DataLen; ++i)
        {
                mpz_class Diff = abs(Data[0] - Data[i]);

                if (Diff > 0)
                {
                        if (0 == MinGcd)
                        {
                                MinGcd = Diff;
                        }
                        else
                        {
                                mpz_class Gcd;

                                mpz_gcd(Gcd.get_mpz_t(), Diff.get_mpz_t(), MinGcd.get_mpz_t());
                               
                                if (Gcd < MinGcd)
                                {
                                        MinGcd = Gcd;
                                }
                        }
                }

                if (Data[i] < MinTime)
                {
                        MinTime = Data[i];
                }
        }

        mpz_class R = MinTime % MinGcd;
        mpz_class Ret;
       
        if (0 == R)
        {
                Ret = 0;
        }
        else
        {
                Ret = MinGcd - R;
        }

        return Ret;
}


int main()
{
        std::ifstream In("in.txt");
        std::string Line;
        int T = 0;
        FILE* Out = fopen("testout.txt", "w");

        In >> T;

        for (int i = 0; i < T; ++i)
        {
                int N = 0;
                std::string Num;
                TMpzVector Data;

                In >> N;

                for (int j = 0; j < N; ++j)
                {
                        In >> Num;
                        Data.push_back(mpz_class(Num));
                }

                mpz_class Result = Calc1(Data);

                gmp_fprintf(Out, "Case #%d: %Zd\n", i + 1, Result.get_mpz_t());
        }

        return 0;
}

顶部
性别:男-离线 阿尔法孝直
(雀力日进)

闽国公
遂安军节度使
★★★★★★

Rank: 19Rank: 19Rank: 19Rank: 19
柱国(正二品) 轩辕春秋年度最佳(游戏人生区)
组别 节度使
级别 卫将军
好贴 2
功绩 1796
帖子 6036
编号 19070
注册 2004-10-16
家族 轩辕雀党


发表于 2010-6-4 01:52 资料 个人空间 短消息 只看该作者 QQ


QUOTE:
原帖由 周瑜 于 2010-5-25 04:46 发表
甲乙面前有两堆豆子,每人轮流取,每次只能从多的那堆取少的那堆豆子数量的整数倍,把其中一堆取完的输掉游戏。

例如两堆豆子分别为 12 和 51,
甲先取,从 51 中拿掉 12 的 3 倍 36 个,剩余数量为 12 和  ...

这个整数是否包括0?
顶部
性别:男-离线 周瑜

栎阳侯谏议大夫

Rank: 16
组别 翰林学士
级别 征西将军
好贴 10
功绩 943
帖子 4716
编号 1808
注册 2003-11-3
家族 瓦岗寨


发表于 2010-6-4 02:03 资料 主页 文集 短消息 只看该作者
没什么原意不原意的,当然要利用各种资源把题做出来。出题者并没有限定语言,有些语言如 Java 和 Python 有内置的大数计算库,自然也可以用 GMP 这样的外置库。

我自己当时花了好几个小时写了个大数类。为了实现除法,写了长整数输入、输出、加法、减法、比较,32位乘长整数,长整数除以长整数但商是32位的试商。除了长整数乘长整数外,几乎把四则运算都实现了,后来看见别人都简单的完成了,才开始学习用库。

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

不包括0,否则游戏无法完成,我把题修改一下。
顶部
性别:男-离线 阿尔法孝直
(雀力日进)

闽国公
遂安军节度使
★★★★★★

Rank: 19Rank: 19Rank: 19Rank: 19
柱国(正二品) 轩辕春秋年度最佳(游戏人生区)
组别 节度使
级别 卫将军
好贴 2
功绩 1796
帖子 6036
编号 19070
注册 2004-10-16
家族 轩辕雀党


发表于 2010-6-4 02:10 资料 个人空间 短消息 只看该作者 QQ


QUOTE:
原帖由 周瑜 于 2010-5-25 04:46 发表
输入格式:
第一行为测试样本数量 T ,以下 T 行每行为一个样本,包含以空格分隔的四个整数 A1,B1,A2,B2。

输出格式:
每一行为 Case #x: y 的格式,其中 x 为1开始的测试样本序号,y 为先手必胜 (A,B) 对的个数。

限制条件:
1 ≤ T ≤ 100
1 ≤ A1 ≤ A2 ≤ 1,000,000
1 ≤ B1 ≤ B2 ≤ 1,000,000

示例输入:
3
5 5 8 8
11 11 2 2
1 6 1 6

示例输出:
Case #1: 0
Case #2: 1
Case #3: 20

样本2:A1=11,B1=11,A2=2,B2=2……好奇怪,A1>A2,B1>B2
样本3:A1=1,B1=6,A2=1,B2=6……这样看来只有1组,怎么结果会是20组呢?

[ 本帖最后由 阿尔法孝直 于 2010-6-4 02:11 编辑 ]
顶部
性别:男-离线 周瑜

栎阳侯谏议大夫

Rank: 16
组别 翰林学士
级别 征西将军
好贴 10
功绩 943
帖子 4716
编号 1808
注册 2003-11-3
家族 瓦岗寨


发表于 2010-6-4 02:17 资料 主页 文集 短消息 只看该作者


QUOTE:
原帖由 阿尔法孝直 于 2010-6-3 14:10 发表


样本2:A1=11,B1=11,A2=2,B2=2……好奇怪,A1>A2,B1>B2
样本3:A1=1,B1=6,A2=1,B2=6……这样看来只有1组,怎么结果会是20组呢?

题目又错了,再改,输入顺序应该是A1,A2,B1,B2
顶部
性别:未知-离线 zhaohaidao

Rank: 5Rank: 5
组别 士兵
级别 破虏将军
功绩 8
帖子 787
编号 31614
注册 2005-1-31
家族 聚贤山庄


发表于 2010-10-23 18:12 资料 短消息 只看该作者


QUOTE:
原帖由 阿尔法孝直 于 2010-5-29 00:51 发表
从右往左数,最右边是第一个开关。

一开始是:

灯—00000000……00000000—电源,第一个断开的开关是通电的,那么按一下按钮之后,最后一个开关状态翻转:
灯—00000000……00000001—电源,此时电流通过 ...

000000000000000000100 的情况下,此时电流到了第四个开关,题目说按一下按钮可以让所有通电开关翻转一次,电流到了第四个开关,那第三个跟第四个开关变不变呢?

顶部
性别:未知-离线 xihai

Rank: 1
组别 百姓
级别 在野武将
功绩 0
帖子 19
编号 305251
注册 2009-1-11


发表于 2010-11-26 20:35 资料 短消息 只看该作者
作记号,等大大
顶部
性别:未知-离线 Maxwell

代王
监管使
枢密直学士
山南西道节度使

Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27
柱国(正二品)
组别 诸侯
级别 征东将军
好贴 4
功绩 1845
帖子 5799
编号 622
注册 2004-7-7


发表于 2010-11-27 12:09 资料 文集 短消息 只看该作者


QUOTE:
原帖由 zhaohaidao 于 2010-10-23 18:12 发表

000000000000000000100 的情况下,此时电流到了第四个开关,题目说按一下按钮可以让所有通电开关翻转一次,电流到了第四个开关,那第三个跟第四个开关变不变呢?


0100的情况下电流到不了第4个开关只到第1个开关,0111的时候电流才到第4个开关。
顶部
性别:男-离线 周瑜

栎阳侯谏议大夫

Rank: 16
组别 翰林学士
级别 征西将军
好贴 10
功绩 943
帖子 4716
编号 1808
注册 2003-11-3
家族 瓦岗寨


发表于 2010-12-19 00:57 资料 主页 文集 短消息 只看该作者
01 链式开关

每个开关翻转的条件是前面所有的开关全部连通,此时按下按钮,此开关可以翻转。如果用二进制数表示,1表示连通,0表示断开,最右侧的数位表示直接与电源相连的开关,则状态
1 0 0 1 0 1 1 1
表示开关1, 2, 3, 5, 8已连通,再次按下按钮时,开关1, 2, 3, 4将翻转,变成
1 0 0 1 1 0 0 0
注意,这种翻转与二进制的增"1"恰好相同。按下 x 次开关后,所有开关表示的整数恰好是 x 的二进制形式。

因此,判断按下 K 次按钮之后,第 N 个开关后的灯泡是否会亮,等同于判断整数 K 的低 N 位是否全部为1,程序可以简单的写出。
顶部
性别:男-离线 周瑜

栎阳侯谏议大夫

Rank: 16
组别 翰林学士
级别 征西将军
好贴 10
功绩 943
帖子 4716
编号 1808
注册 2003-11-3
家族 瓦岗寨


发表于 2010-12-19 07:25 资料 主页 文集 短消息 只看该作者
02 太空观测

本题的两个要点在于最大公约数和长整数计算。

1.由于已知某事件在过去发生时刻 ti (1≤i≤N),因此该事件的最大正周期为 GCD(|t2-t1|, |t3-t2|, ..., |tN-t(N-1)|)。其中函数GCD(...)表示最大公约数。若 ti=t(i+1),则不参与计算。
多个数的最大公约数可以通过逐次结合运算求得:
GCD(a, b, c, d) = GCD(GCD(GCD(a,b), c), d)
因此,只要写出求两个正整数最大公约数的方法,就可以求出多个正整数的最大公约数。
以此最大公约数为周期 T ,便可求得该事件下次发生时刻为:(T - ti MOD T) MOD T

2.最大公约数求法,辗转相除法
假设算式 GCD(a,b) 中 a>b,那么使用 a MOD b 代替参数中的 a,可得到相同的结果。GCD(a,b) = GCD(a MOD b, b)
即使用参数中大数除以小数的余数代替大数,然后反复交替相除取余,直到其中一参数为0,即得到答案。

递归代码

function GCD(a, b)
    if b = 0
       return a
    else
       return GCD(b, a mod b)

非递归代码

function GCD(a, b)
    while b ≠ 0
       t := b
       b := a mod b
       a := t
    return a

3.以上 ti 及最大公约数函数的参数 a,b 都是长整数,不能使用普通的四则运算方法,只能自定义一个长整数类,然后重载各种运算操作符。
由于限制了 ti 最大值不超过 10^50,因此可以使用固定长度的结构,而不用设计动态分配内存,可以简化程序。

我的代码中,实现的方法有:
长整数输入(普通整数和字符串转化为长整数)
长整数输出(屏幕输出和长整数转化为字符串)
长整数比较(大于,小于,等于)
长整数加法(加长整数或者短整数)
长整数减法(减长整数或者短整数)
长整数乘法(乘以短整数)
长整数除法(除以长整数)
长整数取模(除以长整数)
此外,长整数除法和取模中需要用到试商函数,其目的为求出商为短整数的两个长整数相除结果,可以使用二分法实现。
顶部
性别:男-离线 周瑜

栎阳侯谏议大夫

Rank: 16
组别 翰林学士
级别 征西将军
好贴 10
功绩 943
帖子 4716
编号 1808
注册 2003-11-3
家族 瓦岗寨


发表于 2010-12-25 07:50 资料 主页 文集 短消息 只看该作者
03 主题公园

本题题意清晰,直接使用枚举法模拟游客登车过程即可得到结果,可惜这种方法复杂度太高,为O(R∙N)。
当R = 10^8,N = 10^3 时,R∙N = 10^11,超出计算范围。

本题解法可以分为两步进行优化。第一步,求出以每个小组为登车第一小组时,最后登车小组序号和总登车人数,这样,此后只需要O(1)时间即可模拟一次登车过程,复杂度降为O(R);第二步,找出是否存在周期,并根据登车周期求出结果,复杂度进一步降为O(N)。

一、先来看第一步,可以有O(N^2),O(NlogN),O(N)多种方法。

1. 每次登车组数不会超过 N 组,因此直接使用枚举法模拟登车过程,复杂度为O(N^2)。

2. O(NlogN)算法:
把 g 数组复制一遍,附在原数组后面,即:
g[N...2N-1] = g[0...N-1]
定义 S[i] 为 g 数组前 i 项之和,则 S 为递增数组
S[0] = 0
S[i] = S[i-1] + g[i-1]
计算以每组起始登车时可装载的最后一组时,可在 S[i] 到 S[i+N] 之间使用二分法,最后一个不大于 S[i]+k 的项即为最后上车的一组。

3. O(N)算法:
双指针法。第一个指针指向每次登车的第一组,第二个指针指向可装载的最后一组。每当第一个指针向后挪时,第二个指针或者停留原地,或者向后挪动一位或多位。因此,第二个指针不可能反向向前挪动。
第一个指针最多挪动 N 位,第二个指针最多挪动 2N-1 位,因此这复杂度为 O(N)。

二、寻找周期。
所谓周期,指的是从某时刻起,在过山车运行一次或多次后,原来首先登车的一组再次首先登车,此后所有登车情况完全与上一周期相同。
根据鸽巢原理,当运行次数 R 大于游客组数 N 时,周期必然存在。

若 R≤N,可直接得到结果。
若 R>N,可以模拟前 N+1 次登车过程,找出周期长度和开始位置,并求出周期数。

总登车人数 = 周期前登车人数 + 每周期登车人数*周期数 + 周期后登车人数

由于周期长度及周期前、周期后的运行次数均不大于 N,因此这一步和总的算法复杂度也为 O(N)。

[color=Silver][[i] 本帖最后由 周瑜 于 2010-12-25 12:36 编辑 [/i]][/color]
顶部
性别:未知-离线 trichromatic

Rank: 4
组别 校尉
级别 破贼校尉
好贴 2
功绩 11
帖子 58
编号 364075
注册 2010-3-6


发表于 2010-12-26 21:24 资料 文集 短消息 只看该作者
[算了 考虑了一下 还是不贴了 以免打扰大家思维的乐趣。]

贴几个我自己的代码。

07 创建目录

#include<stdio.h>
#include<map>
#include<string>
using namespace std;
class folder
{
public:
        map<string,folder*> Map;
        folder(){}
} *root,*p,*q;
int main()
{
        int _,t,n,m;
        char s[110000];
        scanf("%d",&_);
        for(t=1; t<=_; t++)
        {
                scanf("%d%d",&n,&m);
                int ans=0;
                root=new folder();
                for(int i=0; i<n+m; i++)
                {
                        scanf("%s",s);
                        p=root;
                        for(int j=0;;)
                        {
                                string w="";
                                for(j++; s[j]!=0 && s[j]!='/'; j++)
                                        w+=s[j];
                                if(p->Map.find(w)==p->Map.end())
                                {
                                        p->Map[w]=new folder();
                                        if(i>=n)
                                                ans++;
                                }
                                p=p->Map[w];
                                if(s[j]==0)break;
                        }
                }
                printf("Case #%d: %d\n",t,ans);
        }
        return 0;
}

09 绝对序号

#include<stdio.h>
#define mod 100003
long long int dp[510][510],ans[510];
long long int c[510][510];
void init()
{
        for(int i=0; i<=500; i++)
                for(int j=0; j<=i; j++)
                        if(j==0 || j==i)
                                c[j]=1;
                        else
                                c[j]=(c[i-1][j]+c[i-1][j-1])%mod;
        for(int i=2; i<=500; i++)
        {
                dp[1]=ans=1;
                for(int j=2; j<i; j++)//the rank of i in that set
                {
                        for(int k=1; k<j; k++)//the rank of j in that set
                                dp[j]+=dp[j][k]*c[i-j-1][j-k-1]%mod;
                        dp[j]%=mod;
                        ans+=dp[j];
                }
                ans%=mod;
        }
}
int main()
{
        int _,t,n;
        init();
        scanf("%d",&_);
        for(t=1; t<=_; t++)
        {
                scanf("%d",&n);
                printf("Case #%d: %I64d\n",t,ans[n]);
        }
        return 0;
}

18 修建栅栏

#include<stdio.h>
#include<queue>
#include<utility>
#include<algorithm>
using namespace std;
int n;
long long int a[100],l,g;
long long int gcd(long long int x,long long int y){return y?gcd(y,x%y):x;}
int dp[100010];
priority_queue<pair<int,long long int> > q;
int main()
{
int t,_;
scanf("%d",&_);
for(t=1; t<=_; t++)
{
  scanf("%I64d%d",&l,&n);
  g=0;
  for(int i=0; i<n; i++)
  {
   scanf("%I64d",&a);
   g=gcd(g,a);
  }
  sort(a,a+n);
  printf("Case #%d: ",t);
  if(l%g)
  {
   puts("IMPOSSIBLE");
   continue;
  }
  memset(dp,-1,sizeof(dp));
  dp[0]=0;
  q.push(make_pair(0,0));
  n--;
  int u=a[n];
  while(!q.empty())
  {
   int c=q.top().first;
   long long int l1=-q.top().second;
   q.pop();
   if(dp[c]!=l1)continue;
   for(int i=0; i<n; i++)
   {
    long long int l2=c+a,cost=dp[c]+1;
    if(l2>=u)l2-=u,cost--;
    if(dp[l2]==-1 || dp[l2]>cost)
    {
     dp[l2]=cost;
     q.push(make_pair((int)(l2),-dp[l2]));
    }
   }
  }
  long long int w=l%a[n];
  long long int ans=dp[w]+(l-w)/a[n];
  printf("%I64d\n",ans);
  fprintf(stderr,"%d\n",t);
}
return 0;
}

[ 本帖最后由 trichromatic 于 2010-12-26 22:00 编辑 ]
顶部
性别:未知-离线 Maxwell

代王
监管使
枢密直学士
山南西道节度使

Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27
柱国(正二品)
组别 诸侯
级别 征东将军
好贴 4
功绩 1845
帖子 5799
编号 622
注册 2004-7-7


发表于 2011-4-3 04:31 资料 文集 短消息 只看该作者
02 太空观测



import re

def gcd(x, y) :
    while 0 != y :
        x, y = y, x % y

    return x

def gcd_list(l) :
    while len(l) > 1 :
        x = l.pop()
        y = l.pop()
        l.append(gcd(x, y))

    return l[0]

with open('in.txt') as in_file :
    x = in_file.readline()
    index = 0

    for line in in_file :
        index += 1
        l = re.findall(' \d+', line)
        g = gcd_list(list({abs(int(l[0]) - int(i)) for i in l if i != l[0]}))
        print('Case #{}: {}'.format(index, (g - int(l[0]) % g) % g))



[ 本帖最后由 Maxwell 于 2011-4-3 04:34 编辑 ]
顶部
性别:未知-离线 Maxwell

代王
监管使
枢密直学士
山南西道节度使

Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27
柱国(正二品)
组别 诸侯
级别 征东将军
好贴 4
功绩 1845
帖子 5799
编号 622
注册 2004-7-7


发表于 2011-4-3 12:27 资料 文集 短消息 只看该作者
04 翻转积木



def get_list(file) :
    [n, k] = map(int, file.readline().split(' '))
    l = []

    for i in range(0, n) :
        l.append([ch for ch in file.readline().strip()])

    return n, k, l

def turn_list(l) :
    n = len(l)

    for i in range(0, n) :
        for j in range(n - 1, -1, -1) :
            if '.' == l[i][j] :
                for k in range(j - 1, -1, -1) :
                    if '.' != l[i][k] :
                        l[i][j] = l[i][k]
                        l[i][k] = '.'
                        break

def find_h(l, x, y, ch, n) :
    for i in range(x + 1, x + n) :
        if ch != l[y][i] :
            return False
    return True

def find_v(l, x, y, ch, n) :
    for i in range(y + 1, y + n) :
        if ch != l[i][x] :
            return False
    return True

def find_lt_rb(l, x, y, ch, n) :
    for i in range(1, n) :
        if ch != l[y + i][x + i] :
            return False
    return True

def find_rt_lb(l, x, y, ch, n) :
    for i in range(1, n) :
        if ch != l[y + i][x - i] :
            return False
    return True

def find(l, x, y, ch, n) :
    size = len(l)
    d = {'h': False, 'v': False, 'r': False, 'l': False}

    if size - y >= n :
        d['v'] = True
        if size - x >= n :
            d['h'] = True
            d['r'] = True
        if x >= n - 1 :
            d['l'] = True
    else :
        if size - x >= n :
            d['h'] = True

    r = False

    if d['h'] :
        r = find_h(l, x, y, ch, n)
    if d['v'] and not r :
        r = find_v(l, x, y, ch, n)
    if d['r'] and not r :
        r = find_lt_rb(l, x, y, ch, n)
    if d['l'] and not r :
        r = find_rt_lb(l, x, y, ch, n)

    return r

def main() :
    with open('in03.txt') as in_file :
        t = int(in_file.readline())

        for i in range(1, t + 1) :
            n, k, l = get_list(in_file)
            turn_list(l)

            r = False
            b = False

            for y in range(0, n) :
                for x in range(0, n) :
                    if 'B' == l[y][x] and not b :
                        b = find(l, x, y, 'B', k)
                    elif 'R' == l[y][x] and not r :
                        r = find(l, x, y, 'R', k)

            if r and b :
                print('Case #{}: Both'.format(i))
            elif r :
                print('Case #{}: Red'.format(i))
            elif b :
                print('Case #{}: Blue'.format(i))
            else :
                print('Case #{}: Neither'.format(i))

main()



[ 本帖最后由 Maxwell 于 2011-4-3 21:05 编辑 ]
顶部
性别:未知-离线 Maxwell

代王
监管使
枢密直学士
山南西道节度使

Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27Rank: 27
柱国(正二品)
组别 诸侯
级别 征东将军
好贴 4
功绩 1845
帖子 5799
编号 622
注册 2004-7-7


发表于 2011-4-3 22:33 资料 文集 短消息 只看该作者
07 创建目录



def add(dir_tree, path) :
    l = path.split('/')
    d = dir_tree
    count = 0

    for item in l :
        if None == d.get(item) :
            d[item] = {}
            count += 1

        d = d[item]

    return count

def main() :
    with open('in07.txt') as in_file :
        T = int(in_file.readline())

        for i in range(1, T + 1) :
            dir_tree = {'': {}}
            count = 0
            [N, M] = map(int, in_file.readline().split(' '))

            for j in range(0, N) :
                add(dir_tree, in_file.readline().strip())

            for j in range(0, M) :
                count += add(dir_tree, in_file.readline().strip())

            print('Case #{}: {}'.format(i, count))            
            
main()



顶部

正在浏览此帖的会员 - 共 1 人在线




当前时区 GMT+8, 现在时间是 2024-12-30 22:32
京ICP备2023018092号 轩辕春秋 2003-2023 www.xycq.org.cn

Powered by Discuz! 5.0.0 2001-2006 Comsenz Inc.
Processed in 0.019440 second(s), 9 queries , Gzip enabled

清除 Cookies - 联系我们 - 轩辕春秋 - Archiver - WAP