补题日寄2

思路:初始共计入有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
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值