思路:初始共计入有s种颜色,则第一次最大消去从后往前数出现s种颜色的序列,m1用来计消去前的颜色与数量,m2计消去后的,消去过程,对应m1到m2的转移,如果恰好m2中有m1初始的颜色数量时,消去一次。检测m1是否有0(是否有颜色已经无了)。重置s。
#include<bits/stdc++.h>
using namespace std;
map<int,int> m1,m2;
vector<int> a;
int main(){
int num;
cin>>num;
while(num--){
int n;
m1.clear(),m2.clear(),a.clear();
cin>>n;
for(int i=0;i<n;i++){
int k;
cin>>k;
m1[k]+=1;//m存颜色
a.push_back(k);//a存队列
}
int cnt=0,s=m1.size();
for(int i=n-1;i>=0;i--){
m1[a[i]]--,m2[a[i]]++;//
if(m1[a[i]]==0){
m1.erase(a[i]);
}
if(m2.size()==s){
cnt+=1;
m2.clear();
s=m1.size();
}
}
cout<<cnt<<endl;
}
}
2.
有一串首尾相连的数字,两个玩家轮流操作。 当且仅当相邻22个数字之和为偶数时,可以消除其中一个, 然后可以交换剩下的数字中任意两个数字的位置(也可以不交换)。 特别的,如果只有11个数字,可以直接消除。 最先无法操作的玩家输。 问对于给定的数字串,qcjj(先手)和zn(后手)谁会赢。
注意:首尾相连。操作并没有什么用。最后的状态一定是奇偶交替。并且不存在其他中间卡住的可能性。
#include <bits/stdc++.h>
using namespace std;
int a[30];
int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
if(n%2==0)cout<<"zn"<<endl;
else cout<<"qcjj"<<endl;
}
return 0;
}
3
有三种数量无限的砝码和一个天平,天平的一端有一个质量为 m 的物品,问能否通过放置砝码使得天平平衡?
思路:
裴属定理。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int T,a,b,c,m,k;
cin>>T;
while(T--)
{
cin>>a>>b>>c>>m;
k=gcd(a,b);
k=gcd(k,c);
if(m%k==0)
cout<<"YES\n";
else cout<<"NO\n";
}
}
补充:裴蜀定理:若a,b是整数,且gcd(a,b)= d,那么对于任意的整数x,y,ax+by 都一定是 d 的倍数,特别地,一定存在整数x,y,使 ax+by = d 成立。(根据拓展欧几里得定理得出 ax + by = gcd(a,b))
设题目所给砝码重a,b,c。则它能表示的所有数为gcd(gcd(a,b),c)的倍数。
中国剩余定理:
设m1,m1…mk是两两互质的正整数,则同余方程组:
x = a1(mod m1)
x = a2(mod m2)
………………
x = ak(mod mk)
存在唯一最小整数解使得方程成立。
解决上述问题,首先设N1,N2…Nk满足如下条件:
N1 能被 m2,m3…,mk 整除,而且除以 m1 正好余 1
N2 能被 m1,m3…,mk 整除,而且除以 m2 正好余 1
…
Nk 能被 m1,m2…,mk-1 整除,而且除以 mk 正好余 1
X = N1*a1 + N2*a2 + … + Nk*ak就是我们要求的一个解。
则(X + m1 m2…mk)mod(m1 m2…mk)
就是 x 的最小整数解(这里加上 m1m2…mk 的原因是当 X 为负数时也成立)
N1,N2,…,Nk怎么求?
我们令 M = m1m2…mk,因为Ni | (m1m2…mk) (不包含mi) ,
所以有 Ni = M/mi * A(设 A 为任意整数) 。(1)
又因为 Ni mod mi = 1,所以 Ni = mi * B + 1(B为任意整数)。(2)
综上就得出:M/mi*A = mi*B + 1 => M/mi*A + (-mi)*B = 1
因为 m1 -> mk 都是互质的,所以 (-mi)与 M/mi 也是质数,即 gcd(-mi,M/mi) = 1
欧几里得定理:gcd(a,b)=gcd(b,a mod b)【时间复杂度最差O(logn)】
逆元:若有 a*x ≡ 1 (mod m),则称 x 为a关于m的乘法逆元,等价式 a * x+m * y = 1
费马小定理:如果p是一个质数,而a是一个整数,那么a的p次方减去a本身一定是p的倍数,即a^p ≡ a (mod p)。
扩展欧几里得算法
// 求x, y,使得ax + by = gcd(a, b)
int exgcd(int a, int b, int &x, int &y)
{ //如gcd是1,则x 存放a的模b意义上的逆元
if (!b)
{
x = 1; y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y -= (a/b) * x;
return d;// d is gcd
}