鸽巢原理运用

给定长为 m 的序列 a,求一组 k,l 使得 m|i=klai

第一行输入 m

第二行输入 m 个数字,表示序列 a

输出 k,l

保证 0m2105,0ai103

保证数据在 int 范围内。

题解:证明存在性。若 a1,a1+a2,a1+a2+a3,,a1+a2+a3++am 中有任何一个可以被 m 整除那么结论就成立。设这 m 个和模 m 的余数为 r1,r2,r3,,rm,因为 xmodm 的值只能是 [0,m1],所以定有两个余数相同,这里用到鸽巢原理。

设这两个相同余数为 a1+a2++ak=bm+ra1+a2++al=cm+r。我们将其作差得到 ak+1++al=(cb)m,故 ak+1++al 能被 m 整除。

那么这就优化了暴力枚举,我们用前缀和判同余即可,时间复杂度达到 O(n)

代码:

#include <bits/stdc++.h>
#define rei register int
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define rep(i, s, n, c) for (register int i = s; i <= n; i+=c)
#define repd(i, s, n, c) for (register int i = s; i >= n; i-=c)
#define CHECK cout<<"WALKED"<<endl;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
#define pb push_back
#define ls id<<1
#define rs id<<1|1
const int INF = INT_MAX;
long long binpow(long long a, long long b, ll mod){long long res = 1;  while (b > 0){if (b & 1) res = res * a % mod;a = a * a % mod;  b >>= 1;  }  return res;}

using namespace std;
int a[200005], b[200005];
int main()
{
	int m = read();
	rep (i, 1, m, 1) {
		a[i] = read();
		a[i] += a[i - 1];
	}
	rep (i, 1, m, 1) {
		int r = a[i] % m;
		if (!b[r]) {
			b[r] = i + 1;
		} else {
			printf("%d %d\n", b[r], i);
			break;
		}
	}
    return 0;
}
posted @   Vegdie  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示