poj 2356 Find a multiple 【抽屉原理应用】【在n个数组成的数列中找出若干个连续数使它们之和能被n整除】
来源:互联网 发布:中学生预防网络诈骗 编辑:程序博客网 时间:2024/06/05 04:00
Find a multiple
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 6595 Accepted: 2878 Special Judge
Description
The input contains N natural (i.e. positive integer) numbers ( N <= 10000 ). Each of that numbers is not greater than 15000. This numbers are not necessarily different (so it may happen that two or more of them will be equal). Your task is to choose a few of given numbers ( 1 <= few <= N ) so that the sum of chosen numbers is multiple for N (i.e. N * k = (sum of chosen numbers) for some natural number k).
Input
The first line of the input contains the single number N. Each of next N lines contains one number from the given set.
Output
In case your program decides that the target set of numbers can not be found it should print to the output the single number 0. Otherwise it should print the number of the chosen numbers in the first line followed by the chosen numbers themselves (on a separate line each) in arbitrary order.
If there are more than one set of numbers with required properties you should print to the output only one (preferably your favorite) of them.
If there are more than one set of numbers with required properties you should print to the output only one (preferably your favorite) of them.
Sample Input
512341
Sample Output
223
抽屉原理典型应用:一个由n个数组成的数列 一定能找出若干个连续的数使它们之和能被n整除。
解释:n个数记为a[1],a[2],...a[n].设置一个数组sum,其存储信息为sum[i] = a[1] + a[2] + ...a[i];
情况一:存在一个k(1 <= k <= n),使得sum[k] % n == 0,那么就得证;
情况二:对于任意的k(1 <= k <= n),都有sum[k] % n != 0。 那么 对于n个sum数组的元素将会得到n个余数(即sum[k] % n且这些余数大于0且小于n)。这样对于n个余数(1 <= 余数 <= n-1),我们一定可以找到两个相等的余数,且它们对应sum数组中的start和end元素,使得(sum[end] - sum[start]%n==0。得证。
代码实现: (后面有简单点的思路)
#include <cstdio>#include <cstring>#define MAX 10000+10using namespace std;int a[MAX], sum[MAX], vis[MAX];int main(){int n, i, j;int start, end;//start记录连续数列第一个数的位置 end记录最后一个数的位置 int exist;//判断是否已经找到重复余数int mark;//记录重复的余数 while(scanf("%d", &n) != EOF){memset(vis, 0, sizeof(vis));memset(sum, 0, sizeof(sum));exist = 0; mark = 0; start = end = 0; for(i = 1; i <= n; i++){scanf("%d", &a[i]);if(exist)//已经找到 continue;sum[i] += a[i] + sum[i-1];if(sum[i]%n == 0)//直接能被n整除 {exist = 1;start = 1; end = i; continue;}if(vis[sum[i]%n]) //余数已经出现过{exist = 1;mark = sum[i]%n;//记录重复余数 end = i;//记录结束位置 continue;} else vis[sum[i]%n] = 1;}if(start == 1)//起点从1开始的 {printf("%d\n", end);for(i = 1; i <= end; i++)printf("%d\n", a[i]);}else//起点不是从1开始的 {for(i = 1; i <= n; i++) { if(sum[i]%n == mark)//找到第一个出现重复余数的位置 { start = i+1;//记录位置 break; } } printf("%d\n", end-start+1); for(i = start; i <= end; i++) printf("%d\n", a[i]); }}return 0;}
还有一种更方便的思路:用vis[i]记录余数为i时的数字位置。当检测到a[i]时,余数为k, 若直接整除start = 1,end = i; 若余数k已出现过 start = vis[k]+1,end = i。这样就避免再次查找起点位置的步骤。 还有一点:可以用sum代替sum数组实现。
#include <cstdio>#include <cstring>#define LL long long#define MAX 10000+10using namespace std;LL sum;//防止超intint a[MAX], vis[MAX];int main(){int i, j, n;int exist, start, end;while(scanf("%d", &n) != EOF){sum = 0; exist = 0;memset(vis, 0, sizeof(vis));for(i = 1; i <= n; ++i){scanf("%d", &a[i]);if(exist)continue;sum += a[i];if(sum % n == 0){exist = 1;start = 1;end = i;continue;}if(!vis[sum%n])vis[sum%n] = i;else{exist = 1;start = vis[sum%n]+1;end = i;}}printf("%d\n", end-start+1);for(i = start; i <= end; i++)printf("%d\n", a[i]);}return 0;}
0 0
- poj 2356 Find a multiple 【抽屉原理应用】【在n个数组成的数列中找出若干个连续数使它们之和能被n整除】
- POJ 2356 Find a multiple [抽屉原理]
- POJ-2356 Find a multiple ----抽屉原理
- [POJ 2356]Find a multiple(抽屉原理)
- poj 2356 Find a multiple 抽屉原理
- POJ 2356 Find a multiple <抽屉原理>
- poj 2356 Find a multiple【抽屉原理】
- 将1~m能被7或11整除的所有整数放在数组a中,并通过n返回这些数的个数
- 1~9的9个数组成9位数并前n为能被n整除
- HDU 1796 How many integers can you find(求1到n-1之间能被一个集合A内元素整除的数的个数)
- 在N个数中找出出现奇数次的数
- POJ 3256 Find a multiple (抽屉原理)
- 输出所有1到N之中能被3整除的数之和
- 1到n之间能被m整除的数之和
- POJ 2356 Find a multiple(组合数学-抽屉原理)
- POJ 2356 Find a multiple (抽屉原理)
- POJ-2356 Find a multiple(DFS,抽屉原理)
- 【POJ】2356 - Find a multiple(抽屉原理 & STL)
- 《JAVA与模式》之策略模式
- 8个前沿的 HTML5 & CSS3 效果
- Servlet、Filter和Listener概述
- linux常用命令(2)
- git gui 无法获取你的身份 处理办法
- poj 2356 Find a multiple 【抽屉原理应用】【在n个数组成的数列中找出若干个连续数使它们之和能被n整除】
- HDU 3873 带保护节点的最短路
- C Primer plus 第四章
- 安装Ubuntu 15.04后要做的事
- 黑马程序员————多态、抽象类、接口简述
- 使用telnet发送HTTP请求
- 第1章 快速入门
- 利用NGUI组件简单识别滑动屏幕操作
- 软件开发流程--瀑布模型(Waterfall Model)