POJ2767 Reduced ID Numbers -同余定理

本文探讨了一种寻找最小正整数的问题,该整数能使一组大学学号(SIN)在取模运算后保持唯一性。通过枚举因子及应用同余定理的方法解决此问题,并提供了两种不同的实现方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接 This is the link

Description

T. Chur teaches various groups of students at university U. Every U-student has a unique Student Identification Number (SIN). A SIN s is an integer in the range 0 ≤ s ≤ MaxSIN with MaxSIN = 106-1. T. Chur finds this range of SINs too large for identification within her groups. For each group, she wants to find the smallest positive integer m, such that within the group all SINs reduced modulo m are unique.

Input

On the first line of the input is a single positive integer N, telling the number of test cases (groups) to follow. Each case starts with one line containing the integer G (1 ≤ G ≤ 300): the number of students in the group. The following G lines each contain one SIN. The SINs within a group are distinct, though not necessarily sorted.

Output

For each test case, output one line containing the smallest modulus m, such that all SINs reduced modulo m are distinct.

Sample Input

2
1
124866
3
124866
111111
987651

Sample Output

1
8

Source

Northwestern Europe 2005

题目大意:求解一个最小正整数,使得其它数对其不同余,

思路:枚举每一个因子,判断因子并判断是否同余,

//暴力枚举时间可以过的去,//367MS,注意其中的枝减

This is the link

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include <iomanip>
#include<list>
#include<queue>
#include<sstream>
#include<stack>
#include<string>
#include<set>
#include<vector>
using namespace std;
#define PI acos(-1.0)
#define EPS 1e-8
#define MOD 1e9+7
#define LL long long
#define ULL unsigned long long     //1844674407370955161
#define INT_INF 0x7f7f7f7f      //2139062143
#define LL_INF 0x7f7f7f7f7f7f7f7f //9187201950435737471
const int dr[]={0, 0, -1, 1, -1, -1, 1, 1};
const int dc[]={-1, 1, 0, 0, -1, 1, -1, 1};
// ios.sync_with_stdio(false);
// 那么cin, 就不能跟C的scanf,sscanf,getchar,fgets之类的一起使用了。
#define N 1000000
int a[N+5];
bool p[N+5];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;++i)
            scanf("%d",&a[i]);
        int find;
        for(int i=1; ; ++i)
        {
            find=i;
            for(int j=0;j<=i;++j)//将余数归零
                p[j]=false;
            for(int j=0;j<n;++j)
            {
                int mod=a[j]%i;
                if(p[mod])//表示i有同余的
                {
                    find=0;
                    break;
                }
                p[mod]=true;;//表示这个数的余数
            }
            if(find)
                break;
        }
        printf("%d\n",find);
    }
    return 0;
}

//另一种思路,使用同余定理

同余式 : a ≡ b (mod m) (即 a%m == b%m)

简单粗暴的说就是:若 a-b == m 那么 a%m == b%m

使用同余定理sha筛选出一部分来,然后逐个枚举,判读是否不同余

//感觉用时比上一个长  782MS

This is the link

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include <iomanip>
#include<list>
#include<queue>
#include<sstream>
#include<stack>
#include<string>
#include<set>
#include<vector>
using namespace std;
#define PI acos(-1.0)
#define EPS 1e-8
#define MOD 1e9+7
#define LL long long
#define ULL unsigned long long     //1844674407370955161
#define INT_INF 0x7f7f7f7f      //2139062143
#define LL_INF 0x7f7f7f7f7f7f7f7f //9187201950435737471
const int dr[]={0, 0, -1, 1, -1, -1, 1, 1};
const int dc[]={-1, 1, 0, 0, -1, 1, -1, 1};
// ios.sync_with_stdio(false);
// 那么cin, 就不能跟C的scanf,sscanf,getchar,fgets之类的一起使用了。
#define N 1000000
bool vis[N+5];
int a[N+5];
bool temp[N+5];
int main()
{
    int T;cin>>T;
    while (T--)
    {
        int n;
        scanf("%d",&n);
        memset(vis,0,sizeof(vis));
        for (int i=1;i<=n;++i)
            scanf("%d",a+i);
        for (int i=1;i<=n;++i)
        {
            for (int j=i+1;j<=n;++j)
            {
                int d=abs(a[i]-a[j]);//记录同余的模,只是记录其中的一部分
                vis[d] = 1;
            }
        }
        bool fd=true;
        for (int m=1;fd;++m)
        {
            if (!vis[m])//表示这个数目前没有同余的
            {
                memset(temp,0,sizeof(temp));
                bool ok=true;
                for (int i = 1;ok&&i<=n;++i)//验证是否真的没有同余
                {
                    if (temp[a[i]%m])
                        ok=false;
                    else
                        temp[a[i]%m]=true;
                }
                if (ok)
                {
                    printf("%d\n",m);
                    fd=false;
                }
            }
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值