A. Gregor and Cryptography

题意:

让你选取两个数使得n取模与这两个数相等 ,保证n是素数并且大于5

分析:

我们知道n是素数并且大于5,那么他一定是个奇数,所以我们直接输出2和n-1即可。

B. Gregor and the Pawn Game

题意:

给出你a,b两个数组,然后让你控制b数组的1位置,他可以移动到a数组两种方式:

  • 当b数组i位置是1,如果a数组i位置是0可以一定上面,
  • 当b数组i位置是1,如果a数组(i-1)位置是1可以移动到(i-1)同理可以移动 (i+1)

一个位置最多存放一个,问最多几个?

分析:

直接模拟即可,可以放就放,不可以放就跳过去,三种情况判断,选从i位置是否为0判断,注意标记放1的位置。

ll n;
string str, s;
map<ll, ll>mp;
void solve()
{
mp.clear();
cin >> n;
cin >> str >> s;
ll sum = 0;
for(int i = 0; i < n; i++)
{
if(s[i] == '1')
{
if(mp[i] == 0 && str[i] == '0')
{
sum++;
mp[i] = 1;
}
else if(i - 1 >= 0 && mp[i - 1] == 0 && str[i - 1] == '1')
{
sum++;
mp[i - 1] = 1;
}
else if(i + 1 < n && mp[i + 1] == 0 && str[i + 1] == '1')
{
sum++;
mp[i + 1] = 1;
}
}
}
cout << sum << endl;
}

C. Web of Lies

题意:

n个数,m条边,三种操作:

  1. 添加边u和v保证之前没这个边
  2. 删除边u和v保证之前有这个边
  3. 查询,最后剩几个点,原则是如果这个点上没连边就做出贡献, 连着边把点值最小的去除,最后是都是孤点。

分析:

我们计算边上上值小的点,因为删点是从小往大删,如果,这个点连着一个比他大的点,那么它一定会被删掉,所以我们只需要维护没被他大点连接的数量,每次更新只需要维护是否有比他大的数出入。

ll n,m;
string str, s;
map<ll, ll>mp;
void solve()
{
mp.clear();
scanf("%lld%lld",&n,&m);
ll sum=n;
for(int i=1;i<=m;i++){
ll u,v;
scanf("%lld%lld",&u,&v);
if(u<v) swap(u,v);// u>v;
if(mp[v]==0){
sum--;
}
mp[v]++;
}
ll k;
cin>>k;
while(k--){
ll op;
scanf("%lld",&op);
if(op==3){
printf("%lld\n",sum);
}else if(op==1){
ll u,v;
scanf("%lld%lld",&u,&v);
if(u<v) swap(u,v);// u>v;
if(mp[v]==0){
sum--;
}
mp[v]++;
}else{
ll u,v;
scanf("%lld%lld",&u,&v);
if(u<v) swap(u,v);// u>v;
if(mp[v]==1){
sum++;
}
mp[v]--;
}
}
}

D. Integers Have Friends

题意:

连续一段数对一个数取模之后值相等,对最大长度。

分析:

我们经过对取模后相等,得知,他们的差值一定gcd>1因为只有这样才能取模相等,所以问题就转化成维护区间gcd,找到最长区间gcd>1的长度。 RMQ可以维护,感兴趣可以去学学。

ll gcd(ll a,ll b){
while(b){
ll tmp=a%b;
a=b;
b=tmp;
}
return a;
}
ll a[maxn],b[maxn],n;
ll log_n[maxn];
ll dp[maxn][33];
void LOG(){
log_n[1]=0;
for(int i=2;i<=n+1;i++){
log_n[i]=log_n[i/2]+1;
}
}
void RMQ(){
for(int i=1;i<=n;i++){
dp[i][0]=abs(b[i]);
}
for(int j=1;(1<<j)<=n;j++){
for(int i=1;i+(1<<(j-1))<=n;i++){
dp[i][j]= gcd(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
}
}
ll serch(ll l,ll r){
ll k = log_n[r-l+1];
return gcd(dp[l][k],dp[r-(1<<k)+1][k]);
}
bool check(ll x){
if(x==1) return true;
for(int i=1;i<=n;i++){
ll j=i+x-1;
if(j>n) break;
if(serch(i+1,j)>=2) return true;
}
return false;
}
void solve()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
b[i]=abs(a[i]-a[i-1]);
}
LOG();
RMQ();
ll l=1,r=n;
ll ans=2;
while(l<=r){
ll mid=(l+r)/2;
if(check(mid)) {
ans=mid;
l=mid+1;
}
else r=mid-1;
}
cout<<ans<<endl;


}