翻车
【问题描述】
有一天,小武找到了翻车王,给了他n个整数a1,a2,a3,…an,翻车王需要选择其中的k个数,使得选出的k个数中任意两个的差都可以被m整除。
选出的数可以重复,但不可以超过这n个数中该数的个数。
翻车王不想翻车,所以需要你的帮助。
【输入格式】
第一行包括3个整数n,k,m(2 ≤ k ≤ n ≤ 100000,1 ≤ m ≤ 100000),n,k,m意义见题面。
第二行包括n个数a1,a2,a3,…an(0 ≤ ai ≤ 1000000000)。
【输出格式】
如果不可以选出k个数,使得选出这k个数中任意两个的差都可以被m整除,那么输出“No”。
否则,在第一行输出“Yes”。在第二行输出这k个整数b1,b2,...bk(所选的数字),两两数之间有一个空格。
如果有多种选择k个数字的方案,请输出任意一种。
【输入输出样例】
rollover.in | rollover.out |
4 3 5 2 7 7 7 |
Yes 2 7 7 |
【数据说明】
20%的数据n ≤ 15
50%的数据n ≤ 1000
另外20%的数据m ≤ 1000
100%的数据2 ≤ k ≤ n ≤ 10^5,1 ≤ m ≤ 10^5,0≤ ai ≤10^9
题解
暴力--
用一个循环找开头
for(int i=0;i<n;i++){
flag[i]=1;
if(findnext(a+i,1)) return 0;
flag[i]=0;
}
flag[i]是用来标记第i个书有没有用过了的
if(flag[i]==1)
continue;
findnext()返回bool值
用来判断有没有
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,k,m; 4 int a[100000]; 5 bool flag[100000]; 6 bool findnext(int now[],int len){ 7 if(len>k) return 0; 8 if(len==k) { 9 cout<<"Yes"<<endl; 10 for(int i=0;i<len;i++) 11 cout<<now[i]<<" "; 12 return 1; 13 } 14 for(int i=0;i<n;i++)//寻找下一个 15 { 16 // 17 // for(int debug=1;debug<=len;debug++) cout<<now[debug]<<" "; 18 // cout<<endl; 19 // 20 if(flag[i]==1) 21 continue; 22 bool flagnext=1; 23 for(int j=0;j<len;j++) 24 flagnext=flagnext&&(a[i]-now[j])%m==0; 25 if(!flagnext) continue; 26 //else 27 int flagn = 0; 28 flag[i]=1; 29 now[len]=a[i]; 30 flagn = findnext(now,len+1); 31 now[len]=0; 32 flag[i]=0; 33 return flagn; 34 } 35 return 0; 36 } 37 int main(){ 38 // freopen("rollover.in","r",stdin); 39 // freopen("rollover.out","w",stdout); 40 cin>>n>>k>>m; 41 for(int i=0;i<n;i++) 42 cin>>a[i]; 43 for(int i=0;i<n;i++){ 44 flag[i]=1; 45 if(findnext(a+i,1)) return 0; 46 flag[i]=0; 47 } 48 cout<<"No"; 49 return 0; 50 }
中间的注释(debug)是开始用来调试的。
暴力++
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 const int inf=0X7f7f7f7f; 7 using namespace std; 8 int n,k,m,ans=0,t=inf; 9 int main() 10 { 11 // freopen("rollover.in","r",stdin); 12 cin>>n>>k>>m; 13 long long a[n+1],sum[n+1]; 14 for(int i=1;i<=n;i++) 15 { 16 cin>>a[i]; 17 sum[a[i]%m]++; 18 } 19 for(int i=0;i<m;i++) 20 { 21 if(sum[i]>=k) 22 cout<<"Yes"<<endl; 23 t=i; 24 break; 25 } 26 if(t==inf) 27 cout<<"No"; 28 else 29 for(int i=1;i<=n;i++) 30 { 31 if(a[i]%m==t); 32 { 33 ans++; 34 if(ans<=k) 35 cout<<a[i]<<" "; 36 else break; 37 } 38 } 39 return 0; 40 }
源码来源:https://www.cnblogs.com/YYCether666/p/11185389.html
本来以为会超时的,没想到呀!
std
有关于最小公倍数的数论题
结论:
证明:
设d=gcd(a,b)
a=a'd
b=b'd
所以gcd(a',b')=1,即a',b'互质
题中:a+b是a*b的因子
所以(a'+b')d | a'd*b'd
两边约掉一个d
a'+b' | a'b'd
所以a'+b'<=d
又因为题中:(a'+b')d<=n
所以a'+b'<=sqrt(n)
设k=a'+b'
φ(k)=
等待明天std的下发。。。