HDU 4648 Magic Pen 6

Magic Pen 6

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 399    Accepted Submission(s): 166


Problem Description
In HIT, many people have a magic pen. Lilu0355 has a magic pen, darkgt has a magic pen, discover has a magic pen. Recently, Timer also got a magic pen from seniors.

At the end of this term, teacher gives Timer a job to deliver the list of N students who fail the course to dean's office. Most of these students are Timer's friends, and Timer doesn't want to see them fail the course. So, Timer decides to use his magic pen to scratch out consecutive names as much as possible. However, teacher has already calculated the sum of all students' scores module M. Then in order not to let the teacher find anything strange, Timer should keep the sum of the rest of students' scores module M the same.

Plans can never keep pace with changes, Timer is too busy to do this job. Therefore, he turns to you. He needs you to program to "save" these students as much as possible.
 

Input
There are multiple test cases.
The first line of each case contains two integer N and M, (0< N <= 100000, 0 < M < 10000),then followed by a line consists of N integers a1,a2,...an (-100000000 <= a1,a2,...an <= 100000000) denoting the score of each student.(Strange score? Yes, in great HIT, everything is possible)
 

Output
For each test case, output the largest number of students you can scratch out.
 

Sample Input
2 3 1 6 3 3 2 3 6 2 5 1 3
 

Sample Output
1 2 0
Hint
The magic pen can be used only once to scratch out consecutive students.
 

Source
 

Recommend
zhuyuanchen520
 

題意:有N個數, 取出一個區間的數。  該區間的和要能整除M。  求最大的區間

思路: 水過了。O(n ^ 2)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

//

const int V = 100000 + 50;
const int MaxN = 80 + 5;
const int mod = 10000 + 7;
const __int64 INF = 0x7FFFFFFFFFFFFFFFLL;
const int inf = 0x7fffffff;
int n, m, sum[V], ans;
int main() {
    int i, j;
    while(~scanf("%d%d", &n, &m)) {
        ans = 0;
        for(i = 1; i <= n; ++i) {
            int temp;
            scanf("%d", &temp);
            sum[i] = (sum[i - 1] + temp) % m;
        }
        for(i = n; i >= 1 && i > ans; --i) {
            for(j = 1; j + i - 1 <= n; ++j)
                if((sum[j + i - 1] - sum[j - 1]) % m == 0) {
                    ans = max(ans, i);
                    break;
                }
        }
        printf("%d\n", ans);
    }
}


方法二:  貪心  O(NlogN) 

比上面的N^2慢, 不知道是數據水, 還是可以證明區間一定很接近N.

題目是要求  (sum[i] - sum[j] )% m == 0

那麼只需要將每個 sum[i] % m 然後排序。 判斷該模的最大區間。

這裏的模一定是非負數, 坑了我很久   -2 % 8 = 6  而不是 -2.

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

//

const int V = 100000 + 50;
const int MaxN = 80 + 5;
const int mod = 10000 + 7;
const __int64 INF = 0x7FFFFFFFFFFFFFFFLL;
const int inf = 0x7fffffff;
pair<int, int> pa[V];
int n, m, ans;
int main() {
    int i, j;
    while(~scanf("%d%d", &n, &m)) {
        ans = 0;
        pa[0].first = pa[0].second = 0;
        for(i = 1; i <= n; ++i) {
            int temp;
            scanf("%d", &temp);
            pa[i].first = (pa[i - 1].first + temp) % m;
            pa[i].first = (pa[i].first + m) % m;
            pa[i].second = i;
        }
        sort(pa, pa + n + 1);
        j = 0;
        for(i = 1; i <= n; ++i) {
            if(pa[i].first != pa[j].first)
                j = i;
            ans = max(ans, pa[i].second - pa[j].second);
        }
        printf("%d\n", ans);
    }
}

方法三:  O(N)

但是還是沒有方法一快。無解。

每次只更新模的左右區間。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

//

const int V = 100000 + 50;
const int MaxN = 80 + 5;
const int mod = 10000 + 7;
const __int64 INF = 0x7FFFFFFFFFFFFFFFLL;
const int inf = 0x7fffffff;
int n, m, ans, sum[V];
pair<int, int> Mod[V]; // 模i的區間  [Mod[i].first,  Mod[i].second]
bool vis[V];
int main() {
    int i, j;
    while(~scanf("%d%d", &n, &m)) {
        ans = 0;
        memset(Mod, 0, sizeof(Mod));
        memset(vis, false, sizeof(vis));
        vis[0] = true;
        for(i = 1; i <= n; ++i) {
            int temp;
            scanf("%d", &temp);
            sum[i] = (sum[i - 1] + temp) % m;
            sum[i] = (sum[i] + m) % m;
            if(!vis[sum[i]]) {
                vis[sum[i]] = true;
                Mod[sum[i]].first = i;
            }
            else {
                Mod[sum[i]].second = max(Mod[sum[i]].second, i);
                ans = max(ans, Mod[sum[i]].second - Mod[sum[i]].first);
            }
        }
        printf("%d\n", ans);
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章