3370 Halloween treats 抽屉原理 给定n个数,求其中的任意一个子集满足集合中的每个元素值加和正好是c的倍数

本文介绍了一种解决万圣节孩子们如何公平分配从邻居那里收集到的糖果的算法。该算法通过挑选合适的邻居访问来确保每个孩子都能获得相同数量的糖果,并提供了具体的实现代码。
Halloween treats
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 3242 Accepted: 1205 Special Judge

Description

Every year there is the same problem at Halloween: Each neighbour is only willing to give a certain total number of sweets on that day, no matter how many children call on him, so it may happen that a child will get nothing if it is too late. To avoid conflicts, the children have decided they will put all sweets together and then divide them evenly among themselves. From last year's experience of Halloween they know how many sweets they get from each neighbour. Since they care more about justice than about the number of sweets they get, they want to select a subset of the neighbours to visit, so that in sharing every child receives the same number of sweets. They will not be satisfied if they have any sweets left which cannot be divided.

Your job is to help the children and present a solution.

Input

The input contains several test cases.
The first line of each test case contains two integers c and n (1 ≤ c ≤ n ≤ 100000), the number of children and the number of neighbours, respectively. The next line contains n space separated integers a1 , ... , an (1 ≤ ai ≤ 100000 ), where ai represents the number of sweets the children get if they visit neighbour i.

The last test case is followed by two zeros.

Output

For each test case output one line with the indices of the neighbours the children should select (here, index i corresponds to neighbour i who gives a total number of ai sweets). If there is no solution where each child gets at least one sweet print "no sweets" instead. Note that if there are several solutions where each child gets at least one sweet, you may print any of them.

Sample Input

4 5
1 2 3 7 5
3 6
7 11 2 5 13 17
0 0

Sample Output

3 5
2 3 4
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[110010],vis[110010],s[110010];
int main()
{
    int c,n;
    while(scanf("%d%d",&c,&n)==2&&c)
    {
        int pos,len=0;
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            s[i]=(s[i-1]+a[i])%c;
            if(len) continue;//已经找到解
            int mod=s[i];
            if(mod==0)
            {
                pos=1,len=i;
                continue;
            }
            if(vis[mod]==0)
            {
                vis[mod]=i;
            }
            else
            {
                len=i-vis[mod];
                pos=vis[mod]+1;
            }
        }
        printf("%d",pos);
        for(int i=pos+1;i<pos+len;i++) printf(" %d",i);printf("/n");
    }
    return 0;
}
<think>好的,我需要帮用户用C语言写一个根据当前时间提醒外国节假日的程序。首先,我得理清楚用户的需。用户想要一个程序,能够根据当前系统时间来判断并提醒国外的节假日。这可能包括圣诞节、感恩节、复活节等常见的西方节日。 接下来,我需要考虑如何获取当前的系统时间。在C语言中,通常使用time.h头文件里的函数,比如time()localtime(),来获取当前的日期时间。这部分应该是基础,但需要确保正确获取年月日等信息。 然后是节假日的判断逻辑。不同的节日有不同的计算方式。例如,圣诞节是固定的12月25日,感恩节在美国是11月的第四个星期四,复活节的计算比较复杂,根据春分后的月相来定。我需要为每个节日编写相应的判断函数。 对于固定日期的节日,比如圣诞节,可以直接比较月份日期。对于像感恩节这样的浮动日期,需要计算某个月的第几个星期几。比如,11月的第四个星期四,可以通过遍历11月的日期,找到第四个星期四的具体日期。 复活节的计算较为复杂,可能需要使用特定的算法,比如Anonymous Gregorian算法或者Meeus的算法。这里需要查证正确的计算公式,确保在C语言中正确实现。例如,Meeus的算法步骤包括计算余数、调整因子等,最终确定复活节的月份日期。 接下来,考虑如何将这些节日整合到程序中。可能需要一个结构体数组,存储每个节日的名称、判断函数或日期信息。然后,程序每天运行时检查当前日期是否匹配任何一个节日,如果匹配则发出提醒。 用户提醒的方式可以是控制台输出,比如打印“今天是圣诞节!”之类的信息。如果需要更复杂的提醒,比如弹窗或声音,可能需要调用系统特定的函数,但考虑到跨平台兼容性,控制台输出可能是最安全的选择。 还需要考虑程序的运行频率。如果作为一个常驻程序,可能需要定时检查,比如每隔一分钟检查一次。但在简单的实现中,可能只需用户手动运行程序,程序检查当天是否是节日并输出结果。 另外,时区的问题需要注意。如果用户处于不同的时区,需要确保获取的时间是正确的目标节假日所在的时区。例如,美国的节假日可能需要使用美国时区的时间。这可能需要使用setenv()函数来设置时区,或者使用gmtime()获取UTC时间再转换,但这样可能增复杂性。暂时假设用户使用本地时间,或者程序运行在目标时区的系统上。 测试环节也很重要。需要验证每个节假日的判断函数是否正确,尤其是像复活节这样计算复杂的节日。可以手动输入一些已知日期来测试输出是否正确。 最后,代码的结构要清晰,函数模块化,便于维护扩展。例如,将每个节日的判断逻辑写成单独的函数,方便以后添更多的节日。 可能的挑战包括复活节算法的正确实现,时区处理,以及性能问题(如果节日很多)。不过在这个简单应用中,性能应该不成问题。 总结步骤: 1. 获取当前系统时间。 2. 定义各个节假日的判断函数。 3. 遍历所有节日,检查当前日期是否符合。 4. 输出提醒信息。 现在,根据这些思考,可以开始编写代码了。需要注意语法正确性,比如使用tm结构体的成员(tm_mon从0开始,tm_mday是1-31),月份需要1,年需要1900等细节。</think>以下是用C语言实现根据当前时间提醒外国节假日的分步解决方案: ```c #include <stdio.h> #include <time.h> // 复活节计算(西方算法) void calculate_easter(int year, int* month, int* day) { int a = year % 19; int b = year / 100; int c = year % 100; int d = b / 4; int e = b % 4; int f = (b + 8) / 25; int g = (b - f + 1) / 3; int h = (19*a + b - d - g + 15) % 30; int i = c / 4; int k = c % 4; int l = (32 + 2*e + 2*i - h - k) % 7; int m = (a + 11*h + 22*l) / 451; *month = 3 + (h + l - 7*m + 114) / 31; *day = (h + l - 7*m + 114) % 31 + 1; } // 感恩节(11月第四个星期四) int is_thanksgiving(int mday, int wday, int month) { if (month != 10) return 0; // tm_mon从0开始 return (mday >= 22 && mday <= 28) && (wday == 4); } int main() { time_t now; struct tm *local; time(&now); local = localtime(&now); int year = local->tm_year + 1900; int month = local->tm_mon + 1; // 1-12 int mday = local->tm_mday; // 1-31 int wday = local->tm_wday; // 0-6 (0=周日) printf("当前日期:%04d-%02d-%02d\n", year, month, mday); // 固定日期节日判断 if (month == 1 && mday == 1) { printf("今天是元旦(New Year's Day)\n"); } else if (month == 12 && mday == 25) { printf("今天是圣诞节(Christmas Day)\n"); } else if (month == 11 && mday == 11) { printf("今天是退伍军人节(Veterans Day)\n"); } // 感恩节判断 if (is_thanksgiving(mday, wday, month)) { printf("今天是感恩节(Thanksgiving Day)\n"); } // 复活节判断 int easter_month, easter_day; calculate_easter(year, &easter_month, &easter_day); if (month == easter_month && mday == easter_day) { printf("今天是复活节(Easter Sunday)\n"); } return 0; } ``` **实现原理说明:** 1. **时间获取**: - 使用`time()`获取系统时间戳 - 通过`localtime()`转换为本地时间结构体`tm` - 提取年份(+1900修正)、月份(+1修正)、日期星期信息 2. **固定节日判断**: - 直接比较月份日期 - 例如:元旦(1月1日)、圣诞节(12月25日) 3. **浮动节日判断**: - **感恩节**:11月第四个星期四 - 通过日期范围(22-28日)星期数(周四=4)联合判断 4. **复活节计算**: - 使用天文算法计算(基于春分月圆后的第一个星期日) - 实现Meeus的复活节算法,计算结果存储在`easter_month``easter_day` **扩展建议**: 1. 添更多节日(示例节日可扩展): ```c // 万圣节(10月31日) if (month == 10 && mday == 31) { printf("今天是万圣节(Halloween)\n"); } ``` 2. 增时区处理: ```c setenv("TZ", "America/New_York", 1); // 设置为美国东部时间 tzset(); ``` 3. 定时检查机制: ```c while(1) { // 检查代码 sleep(86400); // 每天检查一次 } ``` **注意事项**: 1. `tm_mon`范围是0-11,需要+1转换为实际月份 2. `tm_wday`中0表示周日,1-6对应周一到周六 3. 复活节算法适用于1583-4099年间的公历计算 4. 不同国家的节日日期可能有差异(如拿大感恩节在10月第二个周一) 此程序运行时将自动检测当前系统时间,并输出当日匹配的国际节日提醒。可以通过添更多节日判断逻辑来扩展功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值