A. Gregor and Cryptography
题意:
题目给定一个≥5的质数 P P P,让你求出两个整数 a a a和 b b b,满足 P P P% a a a= P P P% b b b,且 a < b ≤ P a<b≤P a<b≤P。
思路:
签到题, 没什么好说的,因为P是质数且P≥5,那么P肯定是个奇数,P%2肯定等于1,且P%(P-1)也肯定等于1,所以直接输出2和P-1即可。
代码:
#include<bits/stdc++.h>
//#pragma GCC optimize(2)
using namespace std;
#define int long long
#define fi first
#define se second
#define endl '\n'
#define PII pair<int,int>
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
const int N=1e6+5;
int h[N],e[N],nx[N],idx;
int k,T,t,n,m,ans,cnt;
int a[N];
bool vis[N];
priority_queue <int,vector<int>,greater<int> > q;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>T;
while(T--)
{
int p,a,b;
cin>>p;
cout<<2<<" "<<p-1<<endl;
}
return 0;
}
B、Gregor and the Pawn Game
题意:
给定一个大小为 n ∗ n n*n n∗n的棋盘,给定两个字符串,第一个字符串代表敌方士兵,第二个字符串代表我方士兵,我方士兵位于最下一排,敌方士兵位于最上一排。敌方士兵不动,我方士兵可以向前移动(当其前方没有敌人),若其左前方或右前方有敌方士兵,则他可以斜着走,并把敌方士兵砍死。若字符串的i位置为1,代表当前这个位置有个士兵。让你判断有多少个我方士兵能到达最上方。
思路:
思路也不难想,我们从1~n开始遍历每个位置,若当前这个位置没有我方士兵,则continue。如果当前我方士兵 其左前方有敌方士兵,那么我们优先让我方士兵走左前方,因为这个左前方的位置肯定是其他我方士兵没有到达的(换句话说 就是前面的士兵可以到达这个位置,但是由于他也优先选了左或前,所以这个位置空了下来),若左前方不能走,我们再去判断前方,若前方没有敌方士兵,则可以向前,因为此时无论是在左或是右的我方士兵,都到达不了这个点。(其实优先走中再走左也是可以的),最后再判断能不能走右前方,若能走就走。(我们很容易知道,虽然往右前方走可能会影响后一个士兵向左走,但是一定不会使答案变差)
代码:
#include<bits/stdc++.h>
//#pragma GCC optimize(2)
using namespace std;
#define int long long
#define fi first
#define se second
#define endl '\n'
#define PII pair<int,int>
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
const int N=1e6+5;
int h[N],e[N],nx[N],idx;
int k,T,t,n,m,ans,cnt;
int a[N];
char s1[N],s2[N];
bool vis[N];
priority_queue <int,vector<int>,greater<int> > q;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>T;
while(T--)
{
cin>>n;
cin>>s1+1>>s2+1;
int ans=0,res=0;
s1[0]='0';
s1[n+1]='0';
for(int i=1;i<=n;i++)
{
if(s2[i]=='0') continue;
if(s1[i]=='0') ans++;
else if(s1[i-1]=='1')
{
ans++;
s1[i-1]='2';
}
else if(s1[i+1]=='1')
{
ans++;
s1[i+1]='2';
}
}
cout<<ans<<endl;
}
return 0;
}
C. Web of Lies
题意:
给定n个人,以及m个好友关系,然后接下来m次,让给定的两个人成为朋友。如果一个人有朋友,并且他朋友比他强,那他当场去世。接着给定操作次数q,每次操作有三种,当op为1时,让给定的两个人成为朋友。当op为2时,删除某两个人之间的好友关系。当op为3时,查询有多少人还活着。(!!!!!注意每次查询是独立的!!!!!即当前查询完某些人死了,下次查询相当于这些人原地复活,然后再重新查询,这个点非常关键)
思路:
这题的坑点就是每次查询是独立的,读题如果没注意到这个点就吃大亏了,我就读了半小时假题。我们注意到每个人如果有朋友并且比他强就会把他杀了,那么其实我们只要定义一个数组,记录每个人的朋友 比他强的个数有多少个就行了。一开始我们先把m个关系加上,然后判断此时有多少活人。之后进行操作时,因为先前的关系是还在的,该死了的肯定死了,不需要重新计算的。
具体来说,如果此时操作为1,那么就是将两个人定义为朋友,也就是通过这个操作,会让弱的那个人的 比他强的朋友的个数加1。如果他之前没有比他更强的朋友,那他经过这个操作之后,就会去世了,即答案减1,反之若其有比他更强的朋友,那他早就被砍死了,现在多出来一个砍他的丝毫不影响他的去世(可能只是死的更惨了点hh)。
如果此时操作为2,即删除了两个人的好友关系,也就是让弱的那个人的 比他强的朋友的个数减1,倘若此时 比他强的好友个数为0了,则相当于现在没人杀他了,那么此时活人就多了一个,即让答案加1.
若操作为3时,我们直接输出当前的答案即可。
代码:
#include<bits/stdc++.h>
//#pragma GCC optimize(2)
using namespace std;
#define int long long
#define fi first
#define se second
#define endl '\n'
#define PII pair<int,int>
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
const int N=1e6+5;
int h[N],e[N],nx[N],idx;
int k,T,t,n,m,ans,cnt;
int a[N];
bool vis[N];
priority_queue <int,vector<int>,greater<int> > q;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>m;
int ans=n;
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
if(x>y) a[y]++;
else a[x]++;
}
for(int i=1;i<=n;i++) if(a[i]>0) ans--;
cin>>T;
while(T--)
{
int op,x,y;
cin>>op;
if(op==1)
{
cin>>x>>y;
if(x>y)
{
if(!a[y]) ans--;
a[y]++;
}
else
{
if(!a[x]) ans--;
a[x]++;
}
}
else if(op==2)
{
cin>>x>>y;
if(x>y)
{
a[y]--;
if(!a[y]) ans++;
}
else
{
a[x]--;
if(!a[x]) ans++;
}
}
else cout<<ans<<endl;
}
return 0;
}