CSDN-CSDN社区-.NET技术-C#

收藏 [推荐] 【oj每周推荐】(算法)勇敢的(或许是不幸的)CSDNer[问题点数:100,结帖人:ojlovecd]

  • ojlovecd
  • (OJ)
  • 等 级:
  • 结帖率:
楼主发表于:2009-06-30 14:00:16
10位CSDNer乘坐热气球在太平洋上空旅行,他们打算开香槟庆祝一下这个伟大的时刻。然而很不幸,他们发现气球上破了一个洞,氢气不断外泄,气球开始下降,很快他们就会掉到海洋里成为鲨鱼的甜品。

但他们并没有就此完蛋,只要其中一位能够牺牲自己,跳出气球,就可以挽救其余人的生命。那问题就变成了,谁会愿意这么做呢?有一个公平的办法来解决这个问题。首先,把这十个人从0到9编上号,然后每个人先在纸上写上一个大于等于1小于等于10000的整数,把这10个人写的数字相乘,等到一个结果a,找出a的约数的个数b,则b的个位就是要牺牲自己的CSDNer的编号。把这位英雄找出来吧!!

输入:每行一个大于等于1小于等于10000的整数
输出:b的个位数

样例:
输入:
1
2
6
1
3
1
1
1
1
1

那么a=1*2*6*1*3*1*1*1*1*1=36
a的约数有:1,2,3,4,6,9,12,18,36总共9个
则b=9
那么b的个位也是9
输出:9
回复次数:156
#1楼 得分:0回复于:2009-06-30 14:01:02
题目不难,希望大家在实现目的的同时考虑效率的优化。
  • hikaliv用户头像
  • hikaliv
  • (李博(光宇广贞))
  • 等 级:
#2楼 得分:0回复于:2009-06-30 14:06:23
顶一个,然后看。为什么在.NET 版发算法贴……不在合适呵……
  • clxcxx用户头像
  • clxcxx
  • (大地)
  • 等 级:
#3楼 得分:0回复于:2009-06-30 14:09:45
0.0
#4楼 得分:0回复于:2009-06-30 14:34:11
引用 2 楼 hikaliv 的回复:
顶一个,然后看。为什么在.NET 版发算法贴……不在合适呵……

算法是语言无关的,正因为现在搞.net的很多不注重算法我才会发算法题的
  • zgke用户头像
  • zgke
  • (Cloud)
  • 等 级:
#5楼 得分:5回复于:2009-06-30 14:54:49
乱写的
  private void button3_Click(object sender, EventArgs e)
        {
            ushort[] _Value = new ushort[] { 1 ,2,6,1,3,1,1,1,1,1};

            this.Text = GetDivisorofUint(_Value).ToString();
     
        }

        private int GetDivisorofUint(ushort[] p_ValueNumb)
        {
            ulong _Value = 1;
            for (int i = 0; i != p_ValueNumb.Length; i++)
            {
                _Value = _Value * p_ValueNumb[i];
            }

            Hashtable _HashValue = new Hashtable();

            ulong _Numb = 1;
            while (true)
            {
                if (_HashValue[_Numb] == null)
                {
                    if (_Value % _Numb == 0)
                    {
                        ulong _ValueNumb = _Value / _Numb;
                        if (_HashValue[_ValueNumb] == null) _HashValue.Add(_ValueNumb, null);
                        if (_ValueNumb == _Numb) break;
                        _HashValue.Add(_Numb, null);
                    }
                }
                _Numb++;
                if (_Numb == _Value) break;
            }
            string _Count = _HashValue.Count.ToString();
            return int.Parse(_Count[_Count.Length - 1].ToString());        }
  • phommy用户头像
  • phommy
  • (顽石宫主)
  • 等 级:
#6楼 得分:5回复于:2009-06-30 15:11:47
C# code
using System.Collections.Generic; using System; namespace ConsoleApplication1 { class Program { static Dictionary<int, int> dItems = new Dictionary<int, int>(); //存放据有输入数的质因数 static void Main(string[] args) { int[] Input = new int[10]; //输入 int n, MaxInput = 0; //当前输入,最大输入 //读入输入 for (int i = 0; i < 10; i++) { while (!int.TryParse(Console.ReadLine(), out n) || n <= 0 || n > 10000) { Console.WriteLine("该输入无效,请重新输入(需要1-10000的整数)。"); } Input[i] = n; if (MaxInput < n) { MaxInput = n; } } //求所有程序中可能用到的质数 GetItem(MaxInput); //分解所有整数 for (int i = 0; i < 10; i++) { Split(Input[i]); } //计算约数个数 int Count = 1; foreach (int i in dItems.Values) { Count *= 1 + i; } Console.WriteLine("英雄编号是:" + Count % 10); Console.Read(); } //分解P,表示为 a1^b1+a2^b2+...的形式 private static void Split(int p) { if (p == 1) { return; } if (dItems.ContainsKey(p)) //p是质数 { dItems[p]++; return; } for (int i = 2; i <= p && p > 1; i++) //找P的质因数 { if (p % i == 0) { dItems[i]++; p /= i; i--; } } } static void GetItem(int Max) //筛选法求素数,网上抄了个c的改了下 { int[] sieve = new int[Max + 1]; //Max以内的数 //step 1: //初始化(sieve[i] = 0 表示不在筛中,即不是质数;1表示在筛中) for (int i = 2; i <= Max; i++) //从2开始,因为0和1不是质数 sieve[i] = 1; //step 2: //偶数(2的倍数)肯定不是质数,所以应该先筛除 for (int i = 2; i <= Max / 2; i++) sieve[i * 2] = 0; int p = 2; //第一个质数是2 //step 3:从sieve中删去P的倍数 while (p * p <= Max) { //选下一个p p = p + 1; while (sieve[p] == 0) p++; int t = p * p; int s = 2 * p; while (t <= Max) { sieve[t] = 0; //删除 t = t + s; } } //step 4: 输出结果 for (int i = 2; i <= Max; i++) { if (sieve[i] != 0) { dItems.Add(i, 0); } } } } }
  • phommy用户头像
  • phommy
  • (顽石宫主)
  • 等 级:
#7楼 得分:0回复于:2009-06-30 15:12:50
排版有点乱... 我也不知道为啥...
结果已测试
#8楼 得分:0回复于:2009-06-30 15:13:50
先顶一下,再慢慢来琢磨
  • llsen用户头像
  • llsen
  • (没有功成,何谈隐退)
  • 等 级:
#9楼 得分:0回复于:2009-06-30 15:17:12
借个地

联名贴

支持csdn换回原版面的进


杜绝跨省追捕
  • llsen用户头像
  • llsen
  • (没有功成,何谈隐退)
  • 等 级:
#10楼 得分:0回复于:2009-06-30 15:19:01
引用 9 楼 llsen 的回复:
借个地

联名贴

支持csdn换回原版面的进


杜绝跨省追捕


oj将我的帖子推荐下啊
看下首页
全是觉得这个版面不爽的
#11楼 得分:0回复于:2009-06-30 15:23:26
引用 10 楼 llsen 的回复:
引用 9 楼 llsen 的回复:
借个地

联名贴

支持csdn换回原版面的进


杜绝跨省追捕


oj将我的帖子推荐下啊
看下首页
全是觉得这个版面不爽的


你的帖子在asp.net,我怎么推荐啊?
其实之前就有大批人对新版不爽,没有办法的,即使联名抗议了也不一定会有用。
  • wdgphc用户头像
  • wdgphc
  • (编程有风险,入行需谨慎.)
  • 等 级:
#12楼 得分:0回复于:2009-06-30 15:30:17
请问此题算法只是输入10个数,输出谁被kill掉,还是要找出哪个数被kill掉的几率最小?
  • llsen用户头像
  • llsen
  • (没有功成,何谈隐退)
  • 等 级:
#13楼 得分:0回复于:2009-06-30 15:33:40
引用 11 楼 ojlovecd 的回复:
引用 10 楼 llsen 的回复:
引用 9 楼 llsen 的回复:
借个地

联名贴

支持csdn换回原版面的进


杜绝跨省追捕


oj将我的帖子推荐下啊
看下首页
全是觉得这个版面不爽的


你的帖子在asp.net,我怎么推荐啊?
其实之前就有大批人对新版不爽,没有办法的,即使联名抗议了也不一定会有用。


这个版面影响大家积极性
发这里会被你搞掉
你直接帮我搞非技术区了
呵呵

asp.net版面环境宽松。。。
#14楼 得分:0回复于:2009-06-30 15:34:34
引用 12 楼 wdgphc 的回复:
请问此题算法只是输入10个数,输出谁被kill掉,还是要找出哪个数被kill掉的几率最小?


目前只要输出谁被kill掉即可。
#15楼 得分:1回复于:2009-06-30 15:37:27
虽然我没试过,但我觉得只要大家都把数写大点,百分之九十九是0号牺牲

所以这个方案很不公正
#16楼 得分:0回复于:2009-06-30 15:39:21
学习,不错。
#17楼 得分:0回复于:2009-06-30 15:47:57
先顶一下,感觉不难!!!!!!!!!!!!!!!
  • LQknife用户头像
  • LQknife
  • (安乃定:不吃头疼,吃了上瘾。)
  • 等 级:
#18楼 得分:0回复于:2009-06-30 15:51:46
坐看潮起
  • hikaliv用户头像
  • hikaliv
  • (李博(光宇广贞))
  • 等 级:
#19楼 得分:0回复于:2009-06-30 15:58:29
引用 11 楼 ojlovecd 的回复:
引用 10 楼 llsen 的回复:
引用 9 楼 llsen 的回复:
借个地

联名贴

支持csdn换回原版面的进


杜绝跨省追捕


oj将我的帖子推荐下啊
看下首页
全是觉得这个版面不爽的


你的帖子在asp.net,我怎么推荐啊?
其实之前就有大批人对新版不爽,没有办法的,即使联名抗议了也不一定会有用。


是根本没用!


下次楼主推荐一些牛X点的算法贴吧。本身,我觉得,推荐到首页上去,让人家一看.net版的推荐算法贴仅仅是……是吧……
#20楼 得分:0回复于:2009-06-30 16:01:31
学习了。。。
  • steptodream用户头像
  • steptodream
  • (★熊猫党军委主席★)
  • 等 级:
  • 2

#21楼 得分:5回复于:2009-06-30 16:05:21
C/C++ code
#include <iostream> using namespace std; int SelectPerson(int *P); int main() { int p[10]; int target = 0; for(int i = 0; i < 10; i++) cin >> p[i]; target = SelectPerson(p); if(!target) cout << "Some error occured." << endl; else cout << "The person is " << target%10 << endl; } int SelectPerson(int *p) { int sum = 1; int index = 0; for(int i = 0; i < 10; i++){ sum *= p[i]; } for(int j = 2; j < sum/2; j++){ if(sum%j == 0){ index++; } } return index; }
  • phommy用户头像
  • phommy
  • (顽石宫主)
  • 等 级:
#22楼 得分:0回复于:2009-06-30 16:05:25
修改了下算法,减少些循环次数。另外 可能的话,删掉6楼罢...-_- 最好这次排版不乱

C# code
using System.Collections.Generic; using System; namespace ConsoleApplication1 { class Program { static Dictionary<int, int> dItems = new Dictionary<int, int>(); //存放据有输入数的质因数 static void Main(string[] args) { int[] Input = new int[10]; //输入 int n, MaxInput = 0; //当前输入,最大输入 //读入输入 for (int i = 0; i < 10; i++) { while (!int.TryParse(Console.ReadLine(), out n) || n <= 0 || n > 10000) { Console.WriteLine("该输入无效,请重新输入(需要1-10000的整数)。"); } Input[i] = n; if (MaxInput < n) { MaxInput = n; } } //求所有程序中可能用到的质数 GetItem(MaxInput); //分解所有整数 for (int i = 0; i < 10; i++) { Split(Input[i]); } //计算约数个数 int Count = 1; foreach (int i in dItems.Values) { Count *= 1 + i; } Console.WriteLine(Count % 10); } //分解P,表示为 a1^b1+a2^b2+...的形式 private static void Split(int p) { if (p == 1) { return; } if (dItems.ContainsKey(p)) //p是质数 { dItems[p]++; return; } int[] tmp = new int[dItems.Count]; dItems.Keys.CopyTo(tmp, 0); foreach (int i in tmp) { if (i > p || p <= 1) { break; } while (p % i == 0 && p > 1) { dItems[i]++; p /= i; } } } static void GetItem(int Max) //筛选法求素数,网上抄了个c的改了下 { int[] sieve = new int[Max + 1]; //Max以内的数 //step 1: //初始化(sieve[i] = 0 表示不在筛中,即不是质数;1表示在筛中) for (int i = 2; i <= Max; i++) //从2开始,因为0和1不是质数 sieve[i] = 1; //step 2: //偶数(2的倍数)肯定不是质数,所以应该先筛除 for (int i = 2; i <= Max / 2; i++) sieve[i * 2] = 0; int p = 2; //第一个质数是2 //step 3:从sieve中删去P的倍数 while (p * p <= Max) { //选下一个p p = p + 1; while (sieve[p] == 0) p++; int t = p * p; int s = 2 * p; while (t <= Max) { sieve[t] = 0; //删除 t = t + s; } } //step 4: 输出结果 for (int i = 2; i <= Max; i++) { if (sieve[i] != 0) { dItems.Add(i, 0); } } } } }
  • steptodream用户头像
  • steptodream
  • (★熊猫党军委主席★)
  • 等 级:
  • 2

#23楼 得分:0回复于:2009-06-30 16:07:10
不好意思掉了一句
C/C++ code
#include <iostream> using namespace std; int SelectPerson(int *P); int main() { int p[10]; int target = 0; for(int i = 0; i < 10; i++) cin >> p[i]; target = SelectPerson(p); if(!target) cout << "Some error occured." << endl; else cout << "The person is " << target%10 << endl; return 1; } int SelectPerson(int *p) { int sum = 1; int index = 0; for(int i = 0; i < 10; i++){ sum *= p[i]; } for(int j = 2; j < sum/2; j++){ if(sum%j == 0){ index++; } } return index; }
#24楼 得分:0回复于:2009-06-30 16:09:15
引用 19 楼 hikaliv 的回复:
引用 11 楼 ojlovecd 的回复:
引用 10 楼 llsen 的回复:
引用 9 楼 llsen 的回复:
借个地

联名贴

支持csdn换回原版面的进


杜绝跨省追捕


oj将我的帖子推荐下啊
看下首页
全是觉得这个版面不爽的


你的帖子在asp.net,我怎么推荐啊?
其实之前就有大批人对新版不爽,没有办法的,即使联名抗议了也不一定会有用。


是根本没用!

下次楼主推荐一些牛X点的算法贴吧。本身,我觉得,推荐到首页上去,让人家一看.net版的推荐算法贴仅仅是……是吧……


呵呵,我现在主要服务于新手,毕竟他们才是主要群体,所以我的每周推荐是不会面向高手的。
另外,这个推荐不是我加的,我没想到把它推荐到首页去
  • hikaliv用户头像
  • hikaliv
  • (李博(光宇广贞))
  • 等 级:
#25楼 得分:0回复于:2009-06-30 16:13:56
引用 24 楼 ojlovecd 的回复:
呵呵,我现在主要服务于新手,毕竟他们才是主要群体,所以我的每周推荐是不会面向高手的。
另外,这个推荐不是我加的,我没想到把它推荐到首页去


我还以为你有生杀大权呢。

好吧,我就不在这里水了。
  • ws_hgo用户头像
  • ws_hgo
  • (蓝天白云--(全面提升!!))
  • 等 级:
#26楼 得分:0回复于:2009-06-30 16:16:05
我先看下啊
  • steptodream用户头像
  • steptodream
  • (★熊猫党军委主席★)
  • 等 级:
  • 2

#27楼 得分:0回复于:2009-06-30 16:24:14
把刚才的代码测试了一下 有问题 呵呵
改正了

C/C++ code
#include <iostream> using namespace std; int SelectPerson(int *P); int main() { int p[10]; int target = 0; for(int i = 0; i < 10; i++) cin >> p[i]; target = SelectPerson(p); if(!target) cout << "Some error occured." << endl; else cout << "The person is " << target%10 << endl; return 1; } int SelectPerson(int *p) { int sum = 1; int index = 1; for(int i = 0; i < 10; i++){ sum *= p[i]; } if(sum == 1 ) return sum; cout << sum <<endl; for(int j = 1; j <= sum/2; j++){ if(sum%j == 0){ index++; } } return index; }
#28楼 得分:0回复于:2009-06-30 17:24:36
还以为进错地方了....  原来是版本改了...
#29楼 得分:0回复于:2009-06-30 17:27:05
这贴得顶
#30楼 得分:0回复于:2009-06-30 17:28:54
尊重网上道德。
  • qldsrx用户头像
  • qldsrx
  • (青龙白虎)
  • 等 级:
#31楼 得分:0回复于:2009-06-30 17:49:23
5楼给得很快,看起来也比较简单,就是一个循环,所以也最容易查错了(没别的意思)。
HashTable似乎没有List效率高,if (_HashValue[_ValueNumb] == null)这个判断多余了,因为添加的元素就是null,所以就算存在也是null,等号永远成立,不过后面的添加会报错,因为出现重复键了。
if (_Numb == _Value) break; 改为if (_Numb == _ValueNumb ) break; 的话,效率会更高,因为无需判断是否添加过元素了,也就是不可能出现添加重复键,而且遍历次数是那个10个数乘积的平方根取整数。
其它的没什么,大致思路和我的一致,所以选他的回复修改下。
  • qldsrx用户头像
  • qldsrx
  • (青龙白虎)
  • 等 级:
#32楼 得分:1回复于:2009-06-30 17:51:42
晕,一个笔误,想写大于等于的,忘了修改,版主帮忙删除上面的回复吧。

5楼给得很快,看起来也比较简单,就是一个循环,所以也最容易查错了(没别的意思)。
HashTable似乎没有List效率高,if (_HashValue[_ValueNumb] == null)这个判断多余了,因为添加的元素就是null,所以就算存在也是null,等号永远成立,不过后面的添加会报错,因为出现重复键了。
if (_Numb == _Value) break; 改为if (_Numb >= _ValueNumb ) break; 的话,效率会更高,因为无需判断是否添加过元素了,也就是不可能出现添加重复键,而且遍历次数是那个10个数乘积的平方根取整数。
其它的没什么,大致思路和我的一致,所以选他的回复修改下。
  • cx3232用户头像
  • cx3232
  • (cx3232)
  • 等 级:
#33楼 得分:0回复于:2009-06-30 17:56:37
算了 只是来抢分数的
#34楼 得分:0回复于:2009-06-30 17:57:48
顶起来
  • netgyc用户头像
  • netgyc
  • (Maldini_fans)
  • 等 级:
#35楼 得分:0回复于:2009-06-30 17:58:08
留个记号
#36楼 得分:0回复于:2009-06-30 18:26:19
引用 24 楼 ojlovecd 的回复:
引用 19 楼 hikaliv 的回复:
引用 11 楼 ojlovecd 的回复:
引用 10 楼 llsen 的回复:
引用 9 楼 llsen 的回复:
借个地

联名贴

支持csdn换回原版面的进


杜绝跨省追捕


oj将我的帖子推荐下啊
看下首页
全是觉得这个版面不爽的


你的帖子在asp.net,我怎么推荐啊?
其实之前就有大批人对新版不爽,没有办法的,即使联名抗议了也不一定会有用。


是根本没用!

下次楼主推荐一些牛X点的算法贴吧。本身,我觉得,推荐到首页上去,让人家一看.net版的推荐算法贴仅仅是……是吧……


呵呵,我现在主要服务于新手,毕竟他们才是主要群体,所以我的每周推荐是不会面向高手的。
另外,这个推荐不是我加的,我没想到把它推荐到首页去



我代表新手群体对你谢谢了
#37楼 得分:0回复于:2009-06-30 18:58:34
.
#38楼 得分:5回复于:2009-06-30 19:02:21
我也来发一个,求约数个数的思想和6楼的差不多,分别对输入的数进行质因数分解,以达到对乘积进行质因数分解的目的。然后求约数个数,求的过程中都只取个位。
C# code
namespace FindHero { public class FindHero { public virtual int GetHeroID() { //对各CSDNer输入的数进行排序 SortByNuber(); //求各CSDNer输入的数进行质因数分解 GetSubmultiple(); //将上面的质因数分解结果汇总,即得各CSDNer输入的数的乘积的质因数分解结果 List<int> TotalDivisor = new List<int>(); for (int i = 0; i < CSDNerCount; ++i) { if (_people[i].Number != 1) { TotalDivisor.Add(_people[i].Number); } TotalDivisor.AddRange(_people[i].Divisor); } //对乘积的质因数分解的结果进行排序,以方便统计各质因数出现的次数 TotalDivisor.Sort(); int DivisorCount = 1, HeroID = 1; //统计各质因数出现的次数,同时计算约数个数的个位数 for (int i = 1; i < TotalDivisor.Count; ++i) { if (TotalDivisor[i] == TotalDivisor[i - 1]) { //如果这个质因数和上一个相同,则这个质因数的出现次数加一 ++DivisorCount; } else { //如果这是一个新的质因数,则进行计算,并重置计数器 HeroID = HeroID * (DivisorCount + 1) % 10;//计算约数的个数,但是只需要个位,所以取余 DivisorCount = 1; } } HeroID = HeroID * (DivisorCount + 1) % 10;//将最后一个质因数个数加入计算 return HeroID; } protected virtual void GetSubmultiple() { int StartIndex = 0; int[] HalfNumber = new int[CSDNerCount]; for (int i = 0; i < CSDNerCount; ++i) { HalfNumber[i] = (int)_people[i].Number / 2; } { int i = 2; while (i < HalfNumber[CSDNerCount - 1]) { bool flag; while (i > HalfNumber[StartIndex]) { ++StartIndex; } flag = true; for (int m = StartIndex; m < CSDNerCount; ++m) { if ((_people[m].Number % i) == 0) { _people[m].Number /= i; flag = false; _people[m].Divisor.Add(i); } } if (flag) { ++i; } } } } public virtual void SortByNuber() { int tmpNumber, tmpID; for (int i = 0; i < CSDNerCount - 1; ++i) { for (int m = i + 1; m < CSDNerCount; ++m) { if (_people[i].Number > _people[m].Number) { tmpNumber = _people[i].Number; tmpID = _people[i].ID; _people[i].Number = _people[m].Number; _people[i].ID = _people[m].ID; _people[m].Number = tmpNumber; _people[m].ID = tmpID; } } } } public struct Person { public int ID; public int Number; public List<int> Divisor; } public FindHero() { _people = new Person[CSDNerCount]; for (int i = 0; i < CSDNerCount; ++i) { _people[i].Divisor = new List<int>(); } } public int[] Numbers { get { int[] tmp = new int[CSDNerCount]; for (int i = 0; i < CSDNerCount; ++i) { tmp[i] = _people[i].Number; } return tmp; } set { for (int i = 0; i < CSDNerCount; ++i) { if (value[i] < MIN_VALUE || value[i] > MAX_VALUE) { throw (new OverflowException()); } _people[i].Number = value[i]; _people[i].ID = i; } } } protected const int CSDNerCount = 10, MIN_VALUE = 1, MAX_VALUE = 10000; protected Person[] _people; } class Program { static void Main(string[] args) { int[] Data = new int[10]; FindHero test = new FindHero(); for (int i = 0; i < 10; ++i) { while (!int.TryParse(Console.ReadLine(), out Data[i])) ; } test.Numbers = Data; Console.WriteLine(test.GetHeroID()); } } }
#39楼 得分:1回复于:2009-06-30 20:06:00
怎么感觉题目有点问题啊,编号为0的是无论如何也不会被选到的呀
#40楼 得分:0回复于:2009-06-30 21:05:40
学习了
#41楼 得分:1回复于:2009-06-30 21:14:07
引用 27 楼 steptodream 的回复:
把刚才的代码测试了一下 有问题 呵呵
改正了

C/C++ code
#include <iostream>usingnamespace std;int SelectPerson(int*P);int main()
{int p[10];int target=0;for(int i=0; i <10; i++)
    cin>> p[i];
  target= SelectPerson(p);if(!target)
    cout < <"Some error occured." < < endl;else
    cout < <"The person is" < < target%10 < < endl;return1;
}int SelectPerson(int*p)
{int sum=1;int index=1;for(int i=0; i <10; i++){
    sum*= p[i];
  }if(sum==1 )return sum;
  cout < < sum < <endl;for(int j=1; j <= sum/2; j++){if(sum%j==0){
        index++;
    }
  }return index;
}


兄弟10000的10次方是不是整形越界了!?呵呵!
#42楼 得分:0回复于:2009-06-30 21:44:58
好。。。
  • shunan用户头像
  • shunan
  • (什么是技术)
  • 等 级:
#43楼 得分:1回复于:2009-06-30 23:45:32
1,开辟一个整型数组a[10001],存放10个人的数字之积的各质因数的个数.初始为0
比如36=2^2 * 3^2,也就是说a[2]=2,a[3]=2,其他为0
此步复杂度为,10*(10000以内的数字求质因数个数的复杂度),可以搞个100以内的质数表,这个最多计算100次.总共10*100=1000

2,求此数的约数个数,其实就是把a[1]...a[10000]的值分别加1后相乘,10000复杂度.而且这个值不会越界
(a[2]+1)*(a[3]+1)=9

3,求2中得到的值的个数数即可.
#44楼 得分:0回复于:2009-07-01 00:24:15
顶顶
#45楼 得分:0回复于:2009-07-01 05:20:29
up
  • cdcjk用户头像
  • cdcjk
  • (攀辉)
  • 等 级:
#46楼 得分:0回复于:2009-07-01 07:40:14
学习了
#47楼 得分:0回复于:2009-07-01 08:36:11
up
#48楼 得分:0回复于:2009-07-01 09:04:16
先收藏,现在忙的啊。。。。
  • ojekleen用户头像
  • ojekleen
  • (三尾 灵感害死人)
  • 等 级:
#49楼 得分:0回复于:2009-07-01 09:21:18
引用 36 楼 lqw718106 的回复:
我代表我们新手群体对你谢谢了
  • ojekleen用户头像
  • ojekleen
  • (三尾 灵感害死人)
  • 等 级:
#50楼 得分:0回复于:2009-07-01 09:22:35
我比较建议大家先扔东西,然后脱衣服,然后再考虑其他,哈哈。。
#51楼 得分:0回复于:2009-07-01 10:57:26
来支持下
#52楼 得分:1回复于:2009-07-01 11:05:44
- -我去调试试试

其实我好奇那哪个数字的可能性比较大
  • xsir317用户头像
  • xsir317
  • (抵制国货)
  • 等 级:
#53楼 得分:0回复于:2009-07-01 11:33:21

气球上有笔记本?有的话还不赶紧扔下去?

没有?没有你们折腾个毛算法啊。。。
  • phommy用户头像
  • phommy
  • (顽石宫主)
  • 等 级:
#54楼 得分:0回复于:2009-07-01 11:36:55
引用 52 楼 hilarymoggy 的回复:
- -我去调试试试

其实我好奇那哪个数字的可能性比较大


上面有人说了...0的可能性最大...
考查约数个数公式 (a1+1)(a2+1)(a3+1)...,只要所有乘数中出现一个10的倍数,或者同时有5和2的倍数, 0号就悲剧了-_-
#55楼 得分:0回复于:2009-07-01 11:39:14
名帖~留名~!
  • phommy用户头像
  • phommy
  • (顽石宫主)
  • 等 级:
#56楼 得分:0回复于:2009-07-01 11:51:37
凑了一个组合
8585
5151
3434
1717
1919
1919
1919
1919
101

如果1-9号这样选择的话,0号无论选择什么数都会被扔出去-_-
#57楼 得分:1回复于:2009-07-01 13:22:34
说说我的看法, 每个人写的数字可以写成素数的乘积,则10个人的数字很容易也转成素数的乘积,在高代中有一个公式是可以计算的,a1^p1 * a2^p2..., 其中a1,a2这些全部是素数,则有因子数是(a1+1)(a2+1)(...)..  所以问题就解决了
  • combai用户头像
  • combai
  • (七支玫瑰QQ群:6846876)
  • 等 级:
#58楼 得分:0回复于:2009-07-01 13:54:41
路过,看看
#59楼 得分:0回复于:2009-07-01 14:03:43
引用 50 楼 ojekleen 的回复:
我比较建议大家先扔东西,然后脱衣服,然后再考虑其他,哈哈。。

现在大家都裸体了,东西也没得扔了,屎尿也没得拉了,怎么办???
  • outou用户头像
  • outou
  • (冰凝)
  • 等 级:
#60楼 得分:0回复于:2009-07-01 14:08:03
收藏
#61楼 得分:0回复于:2009-07-01 14:10:03
顺便学习学习
  • phommy用户头像
  • phommy
  • (顽石宫主)
  • 等 级:
#62楼 得分:0回复于:2009-07-01 14:46:52
引用 59 楼 sbwwkmyd 的回复:
引用 50 楼 ojekleen 的回复:
我比较建议大家先扔东西,然后脱衣服,然后再考虑其他,哈哈。。

现在大家都裸体了,东西也没得扔了,屎尿也没得拉了,怎么办???


祈祷自己不被抽中...
如果不幸被抽中,有两种选择...
1.起义! 遵守规则会死,违反了可能活,你怎么选?
2.体力不占优势第1条行不通的话,可以和大家商量一下能不能先扔两条腿下去,不行再扔手啊啥的...
#63楼 得分:0回复于:2009-07-01 15:06:50
很简单的一道题啊,

从算法,到优化 都非常之简单。
#64楼 得分:1回复于:2009-07-01 15:12:23
使用 2 作为 素数数组的第一个元素 ,初始明显是1

然后从3开始到最大数一直找,
去除 素数数组的每一个元素,用于判断 是否 是素数,
如果是素数, 加入到素数数组中,使其总数+1.

这样可快速得到 素数数组集合。


第二步,
使用这些素数 去 整除  之前的 那个乘积,
得到 若干 素数 和 此素数个数
则的 (num1+1)*(num2+1)...*(numn+1),

取个位,完毕。


#65楼 得分:0回复于:2009-07-01 15:12:51
初始明显是1 长度
  • tietao用户头像
  • tietao
  • (tietao)
  • 等 级:
#66楼 得分:5回复于:2009-07-01 15:15:57
我刚学C,来试一下,不知是否对,还请楼主评判

#include <stdio.h>
#include <math.h>
#define  N  10
void main()
{
        int a[N],*p=a;
int j=0;
long int  i,sum=1;
puts("Please input ten numbers:");
for(;p <N+a;p++)
{
    scanf("%d",p);
}
for(p=a;p <N+a;p++)
  sum*=*p;
    for(i=1;i <=sum;i++)
{
      if(sum%i==0)
  j++;
}
printf("the number of common divisor is: %d\n",j);

}
  • ilysony用户头像
  • ilysony
  • (J2EE QQ群:431182)
  • 等 级:
#67楼 得分:0回复于:2009-07-01 15:19:18
MAKER
#68楼 得分:1回复于:2009-07-01 15:42:45
呵呵,合数都可以转化为X=a0^i*a1^i2....an^in的形式,而a0-an是小于10^4的素数,分别对每个数求出其含素数的个数[一个while即可],然后统计在一起,可以用hash <int, int>来统计之。
然后的问题就是,a0^i1*a1^i2....an^in这种形式能组合出多少种不同约数,可以转化组合数也可以看为0,1背包,一定是 连乘(2^ix-1)[x->1...n],最后与10求模,最终即为所求。代码就略去了,应该能在30-40行左右搞定。一点优化,个位肯定只由个位决定,所以连乘((2^ix-1)%10)可以避免越界哈!
楼主用心良苦,做应用的人还是应该多修内功,这个才是程序之道呀!下次发点DP之类的吧,比较练思维。
  • silentwins用户头像
  • silentwins
  • (原谅我当天不懂得珍惜只知任性.)
  • 等 级:
  • 2

    2

    2

#69楼 得分:0回复于:2009-07-01 16:03:12
题目改成谁被Kill的几率最少,复杂度会上升2个档次,哈哈~~
#70楼 得分:0回复于:2009-07-01 16:10:17
引用 69 楼 silentwins 的回复:
题目改成谁被Kill的几率最少,复杂度会上升2个档次,哈哈~~


呵呵,是的,所以谁有兴趣的话可以尝试一下
#71楼 得分:0回复于:2009-07-01 16:16:59
好好学习,天天向上,争取早日涨工资
#72楼 得分:0回复于:2009-07-01 16:26:04
引用 54 楼 phommy 的回复:
引用 52 楼 hilarymoggy 的回复:
- -我去调试试试

其实我好奇那哪个数字的可能性比较大


上面有人说了...0的可能性最大...
考查约数个数公式 (a1+1)(a2+1)(a3+1)...,只要所有乘数中出现一个10的倍数,或者同时有5和2的倍数, 0号就悲剧了-_-


- -话说,我没懂……
如果是9个1和1个10呢?那不就是4么?
如果是7个1和1个10 一个5 一个2呢?是9吧?
我觉得好像差不多啊
  • phommy用户头像
  • phommy
  • (顽石宫主)
  • 等 级:
#73楼 得分:0回复于:2009-07-01 16:34:36
引用 69 楼 silentwins 的回复:
题目改成谁被Kill的几率最少,复杂度会上升2个档次,哈哈~~


好像更简单了,只要求两自然数相乘,个位数的几率就好了
C# code
static void Main(string[] args) { double[] module = new double[10]; //放10个数,第i位是指i乘以随机数后个位为i的几率。 //计算module for (int i = 0; i < 10; i++) { module[i] = 0; } for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { module[i * j % 10] += 0.1; } } //输出 double s = 0; for (int i = 0; i < 10; i++) { s += module[i]; Console.WriteLine("rate of {0}: {1:00.00}%", i, module[i] * 10); } Console.Read(); }


rate of 0: 27.00%
rate of 1: 04.00%
rate of 2: 12.00%
rate of 3: 04.00%
rate of 4: 12.00%
rate of 5: 09.00%
rate of 6: 12.00%
rate of 7: 04.00%
rate of 8: 12.00%
rate of 9: 04.00%
  • phommy用户头像
  • phommy
  • (顽石宫主)
  • 等 级:
#74楼 得分:0回复于:2009-07-01 16:40:58
0最悲剧,下面是2,4,6,8(不出所料,偶数集体悲剧了),然后是5(预计之中,5*奇数=5),其它的并列

上面程序计算的名次有效,概率无效,没有考虑“10000”这个限定条件来规定迭代次数。
#75楼 得分:0回复于:2009-07-01 16:45:09
引用 74 楼 phommy 的回复:
0最悲剧,下面是2,4,6,8(不出所料,偶数集体悲剧了),然后是5(预计之中,5*奇数=5),其它的并列

上面程序计算的名次有效,概率无效,没有考虑“10000”这个限定条件来规定迭代次数。

话说不是约数和的个位数么?0.0
- -我算法真差……
  • huqiub用户头像
  • huqiub
  • (huqiub)
  • 等 级:
#76楼 得分:0回复于:2009-07-01 17:54:13
先顶下  在看看
#77楼 得分:0回复于:2009-07-01 18:43:23
编程比分析设计要好的多
#78楼 得分:0回复于:2009-07-01 18:59:33
挺有意思
#79楼 得分:0回复于:2009-07-01 19:20:57
恩,楼上很幽默……
  • mikier用户头像
  • mikier
  • (mikier)
  • 等 级:
#80楼 得分:0回复于:2009-07-01 19:55:14
引用 27 楼 steptodream 的回复:
把刚才的代码测试了一下 有问题 呵呵
改正了

C/C++ code
#include <iostream>usingnamespace std;int SelectPerson(int*P);int main()
{int p[10];int target=0;for(int i=0; i <10; i++)
    cin>> p[i];
  target= SelectPerson(p);if(!target)
    cout < <"Some error occured." < < endl;else
    cout < <"The person is" < < target%10 < < endl;return1;
}int SelectPerson(int*p)
{int sum=1;int index=1;for(int i=0; i <10; i++){
    sum*= p[i];
  }if(sum==1 )return sum;
  cout < < sum < <endl;for(int j=1; j <= sum/2; j++){if(sum%j==0){
        index++;
    }
  }return index;
}


这里要的是约数的个数,不应该只算一部分的, j <=sum,而不是sum/2
#81楼 得分:1回复于:2009-07-01 20:14:52
我想这里还不如考虑改方案是否公平,是否有某种选数方案可以令部分人大大受益或者令部分人大大危险呢?
还有,我想问问34楼,为何说0号是无论如何都是免灾的呢?是说0号可以选某种号码,使得无论他人如何选数都不会波及自己吗? 因为(比如):如果有1人选1,9人选2,那么就是0号遭殃啦。
我想这个问题还是不简单的,
#82楼 得分:0回复于:2009-07-01 20:35:16
回复 56 楼和 57 楼 的一些误判
57楼笔误,因子数是:(q1+1)(q2+1)。。。。而非(a1+1)(a2+1)...
56 楼逻辑有误:因子公式已经指出了,每个人都可以为改变表达式的积做出贡献,比如:
(1) 如果前面九个人的连乘积是:(q1+1)*(q2+1)*...*(q9+1),那么,如果你想改变其中第二和第五个的乘项,就令你的选号比如是a5的Q5次方与a2的Q2次方的乘积,这样,表达式中的第五项和第二项就发生了变化,很有可能导致最后的结果的个位数也发生变化,
(2)由此,0号选手可能不经意间就对另9个表达式的乘积产生了重大改变,所以,仅仅根据这个公式,不能
直接得出0号存在必死的可能
#83楼 得分:0回复于:2009-07-01 20:51:37
如果这十个人里有1为非常聪明的人,而另外九名都是随机选数没有太多的聪明想法,那么,如果这位聪明的人是第奇数号,他完全可以选择一个尽可能大的素数,如果别人选的数没有一个是该素数的倍数(或者是该素数的奇数次幂的倍数),那么这个聪明人就幸免了,因为它为最终的因子表达式贡献的独特的项2(或者是4,6,。。。),从而因子表达式变成了(q0+1)*...*(1+1)*...*(q9+1);
由于他选了特别大的素数(不能选3这样的小的数),别人随机与他相重(已经不能是他的倍数了)的概率近乎为0了
#84楼 得分:0回复于:2009-07-01 23:30:57
大整数啊~~~继续想。。。。
#85楼 得分:1回复于:2009-07-01 23:41:44
1,2,6,1,3,1,1,1,1,1
对每个数分解得约数位:
1,2,2,3,3,1,1,1,1,1,1
然后每个数和剩余的数相乘得为要求的约数
重复的不统计。
时间复杂度起码有平方级,需优化。
  • ChrisAK用户头像
  • ChrisAK
  • (其实我就是一茶几...)
  • 等 级:
#86楼 得分:0回复于:2009-07-01 23:58:55
我觉得当他们算出来后会发现已经掉到海里了
#87楼 得分:5回复于:2009-07-02 00:28:24
C/C++ code
#include "stdio.h" #include "math.h" void main() { long i,t,j=1,k=0; for(i=1;i<=10;i++) { scanf("%ld",&t); j*=t; } for(i=1;i<=j;i++) if(j%i==0) k++; printf("%d",k%10); }
#88楼 得分:0回复于:2009-07-02 00:40:52
我发现···我天真了····
#89楼 得分:0回复于:2009-07-02 01:01:40
收藏
#91楼 得分:1回复于:2009-07-02 08:31:49
首先,简单的把10个数相乘,其结果范围在1~1e40,64位绝对容纳不下,而且效率低下
其次,要求约数的个数,可以使用排列组合的方法,计算每个质数的个数,
支持43楼

#92楼 得分:0回复于:2009-07-02 08:54:43
DJDJ
  • phommy用户头像
  • phommy
  • (顽石宫主)
  • 等 级:
#93楼 得分:0回复于:2009-07-02 09:13:54
引用 82 楼 wangxugangzy05 的回复:
回复 56 楼和 57 楼 的一些误判
57楼笔误,因子数是:(q1+1)(q2+1)。。。。而非(a1+1)(a2+1)...
56 楼逻辑有误:因子公式已经指出了,每个人都可以为改变表达式的积做出贡献,比如:
(1) 如果前面九个人的连乘积是:(q1+1)*(q2+1)*...*(q9+1),那么,如果你想改变其中第二和第五个的乘项,就令你的选号比如是a5的Q5次方与a2的Q2次方的乘积,这样,表达式中的第五项和第二项就发生了变化,很有可能导致最后的结果的个位数也发生变化,
(2)由此,0号选手可能不经意间就对另9个表达式的乘积产生了重大改变,所以,仅仅根据这个公式,不能
直接得出0号存在必死的可能


需要考虑其它条件。
我在56楼楼举的例子,0号如果想活命,最小的选择是10302,已经超过“10000”的限制了。换句话说,这九个数的积
8585
5151
3434
1717
1919
1919
1919
1919
101
,再乘以任何10000以内的数,得到的约数个数必然是10的倍数
#94楼 得分:0回复于:2009-07-02 10:31:28
好像有个什么算法可以算出约数个数的,忘了叫什么。
#95楼 得分:0回复于:2009-07-02 14:40:44
算法不错
#96楼 得分:5回复于:2009-07-02 15:19:03
这类比性能的算法最好提供一个统一的代码框架和测试数据。

C# code
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { const int maxNumber = 1000; // 最大的数字范围 const int toll = 10; // 人数 #region 生成测试数据 //var cards = new int[] { 1, 2, 6, 1, 3, 1, 1, 1, 1, 1 }; var cards = new int[toll]; // 每个人写出的数字 var random = new Random(); for (var i = 0; i < cards.Length; i++) cards[i] = random.Next(maxNumber) + 1; #endregion 生成测试数据 #region 统计约数出现的次数 var divisor = new Dictionary<int, int>(); for (var j = 0; j < cards.Length; j++) { var i = 2; while (cards[j] > 1) { if (cards[j] % i == 0) { if (divisor.ContainsKey(i)) divisor[i]++; else divisor[i] = 1; cards[j] /= i; } else i += i == 2 ? 1 : 2; } } #endregion 统计约数出现的次数 #region 计算约数个数 var sum = 1; foreach (var i in divisor) if (i.Value > 0) sum *= (i.Value + 1); #endregion 计算约数个数 Console.WriteLine(sum % toll); Console.Read(); } } }
蹭分。。。
#97楼 得分:0回复于:2009-07-02 15:25:45
引用 86 楼 chrisak 的回复:
我觉得当他们算出来后会发现已经掉到海里了
给楼主10秒钟算出来,算不出来就丢海里。
#98楼 得分:0回复于:2009-07-02 16:13:55
引用 97 楼 zswang 的回复:

给楼主10秒钟算出来,算不出来就丢海里。


可以直接把我丢海里了……
#99楼 得分:0回复于:2009-07-02 16:47:40
引用 98 楼 ojlovecd 的回复:
引用 97 楼 zswang 的回复:

给楼主10秒钟算出来,算不出来就丢海里。


可以直接把我丢海里了……

楼主提议真好

- -真奉献……
#100楼 得分:5回复于:2009-07-02 16:54:40

#include <iostream.h>
void getHero(){
    int incomeList[10];
    int N=10000;
    int i=0;
    while(i <10){
          cin>>incomeList[i];
          if(incomeList[i]>0&&incomeList[i] <10000){
              i++;
          }
    }
    int prime[1250];
    int tempList[1250];
    int tag[10000];
    int cnt = 0;
    for (i = 2; i < N; i++)
    {
        if (!tag[i])   
        {
            prime[cnt++] = i;
            tempList[cnt]=0;
        }
        for (int j = 0; j < cnt && prime[j] * i < N; j++)
        {
            tag[i*prime[j]] = 1;
            if (i % prime[j] == 0)
                break;
        }
    }
   
    for(i=0;i <10;i++){
        int temp = incomeList[i];
        int j=0;
        while(j <cnt-1 && temp>=prime[j]){
            if(temp%prime[j]==0){
                temp=temp/prime[j];
                tempList[j]=tempList[j]+1;
            }
            else{
              j++;
            }
        }
    }
   
    int aa=1;
    for(i=0;i <cnt-1;i++){
      if(tempList[i]>0){
      aa=aa*(tempList[i]+1);
      }
    }
    cout < <aa%10 < <endl;
    cin>>i;


int main(){         

    getHero();
         
}

用线性找一万以内的素数表,再依次记录每一个数中每个素数出现的次数。最后,将出现过的素数个数+1相乘,就可以得到结果。
比如如果在十个数中,5出现了3次,7出现了1次,则最后的因数个数一定是(3+1)*(1+1)=8个。
这个兄弟们自己证明一下哟。
这是我能想到的解决效率的办法了。有好办法记得跟我说一下。