Codeforces Round #736 (Div. 2) (A-D)
阿新 • • 發佈:2021-08-02
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條邊,三種操作:
- 新增邊u和v保證之前沒這個邊
- 刪除邊u和v保證之前有這個邊
- 查詢,最後剩幾個點,原則是如果這個點上沒連邊就做出貢獻, 連著邊把點值最小的去除,最後是都是孤點。
分析:
我們計算邊上上值小的點,因為刪點是從小往大刪,如果,這個點連著一個比他大的點,那麼它一定會被刪掉,所以我們只需要維護沒被他大點連線的數量,每次更新只需要維護是否有比他大的數出入。
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;
}