本场链接:Codeforces Round #713 (Div. 3)
A. Spy Detected!
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
typedef pair<int,int> pii;
#define x first
#define y second
const int N = 105;
int a[N];
int main()
{
int T;scanf("%d",&T);
while(T--)
{
int n;scanf("%d",&n);
map<int,int> st;
forn(i,1,n)
{
scanf("%d",&a[i]);
++st[a[i]];
}
forn(i,1,n)
{
if(st[a[i]] == 1)
{
printf("%d\n",i);
break;
}
}
}
return 0;
}
B. Almost Rectangle
注意越界情况
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
typedef pair<int,int> pii;
#define x first
#define y second
const int N = 405;
char s[N][N];
int main()
{
int T;scanf("%d",&T);
while(T--)
{
int n;scanf("%d",&n);
forn(i,1,n) scanf("%s",s[i] + 1);
int x1 = -1,y1,x2,y2;
forn(i,1,n) forn(j,1,n)
{
if(s[i][j] == '.') continue;
if(x1 == -1) x1 = i,y1 = j;
else x2 = i,y2 = j;
}
if(x1 == x2)
{
if(x1 + 1 <= n) s[x1 + 1][y1] = s[x2 + 1][y2] = '*';
else s[x1 - 1][y1] = s[x2 - 1][y2] = '*';
}
else if(y1 == y2)
{
if(y1 + 1 <= n) s[x1][y1 + 1] = s[x2][y2 + 1] = '*';
else s[x1][y1 - 1] = s[x2][y2 - 1] = '*';
}
else s[x2][y1] = s[x1][y2] = '*';
forn(i,1,n) printf("%s\n",s[i] + 1);
}
return 0;
}
C. A-B Palindrome
特别的:在第一轮循环的时候仅限于处于一边是问号一边不是的,因为做到一半可能需要的1
会比0
更多,但是从整体上来看填0
会更好。放到后面处理,混在一起无法判断。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
typedef pair<int,int> pii;
#define x first
#define y second
const int N = 2e5+7;
char s[N];
int main()
{
int T;scanf("%d",&T);
while(T--)
{
int a,b;scanf("%d%d",&a,&b);
int n = a + b,need0 = 0,need1 = 0;
scanf("%s",s + 1);
forn(i,1,n) if(s[i] == '0') ++need0;else if(s[i] == '1') ++need1;
need0 = a - need0,need1 = b - need1;
if(need0 < 0 || need1 < 0)
{
puts("-1");
continue;
}
bool ok = 1;
forn(l,1,n / 2)
{
int r = n - l + 1;
if(s[l] == s[r])
{
continue;
}
else
{
if(s[l] != '?') swap(s[l],s[r]);
if(s[l] != '?')
{
ok = 0;
break;
}
if(s[r] == '0')
{
if(!need0)
{
ok = 0;
break;
}
--need0;
s[l] = '0';
}
else
{
if(!need1)
{
ok = 0;
break;
}
--need1;
s[l] = '1';
}
}
}
forn(l,1,n / 2)
{
int r = n - l + 1;
if(s[l] == s[r] && s[l] == '?')
{
if(need1 >= need0)
{
if(need1 < 2)
{
ok = 0;
break;
}
need1 -= 2;
s[l] = '1';s[r] = '1';
}
else
{
if(need0 < 2)
{
ok = 0;
break;
}
need0 -= 2;
s[l] = '0';s[r] = '0';
}
}
}
if(n % 2)
{
if(s[(n + 1) / 2] == '?')
{
if(!need1 && !need0)
{
ok = 0;
break;
}
else if(need1)
{
--need1;
s[(n + 1) / 2] = '1';
}
else
{
--need0;
s[(n + 1) / 2] = '0';
}
}
}
if(need1 || need0) ok = 0;
if(!ok) puts("-1");
else printf("%s\n",s + 1);
}
return 0;
}
D. Corrupted Array
特判:\(x = b[n + 1]\)的情形。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
const int N = 2e5+7;
ll b[N];
int main()
{
int T;scanf("%d",&T);
while(T--)
{
int n;scanf("%d",&n);
ll sum = 0;
map<ll,int> st;
forn(i,1,n + 2) scanf("%lld",&b[i]),sum += b[i],++st[b[i]];
bool ok = 0;
ll x = -1;
forn(i,1,n + 2)
{
if((sum - b[i]) % 2) continue;
--st[b[i]];
if(st.count((sum - b[i]) / 2) && st[(sum - b[i]) / 2])
{
ok = 1;
x = b[i];
break;
}
++st[b[i]];
}
if(!ok) puts("-1");
else
{
bool xflag = 0,sflag = 0;
forn(i,1,n + 2)
{
if(b[i] == x && !xflag)
{
xflag = 1;
continue;
}
else if(b[i] == (sum - x) / 2 && !sflag)
{
sflag = 1;
continue;
}
printf("%lld ",b[i]);
}
puts("");
}
}
return 0;
}
E. Permutation by Sum
容易想到一个结论:求出一段区间能构造出来的最小答案和最大答案,在这之间的答案都可以构造出来。
对于\(n\)个数填进\(k\)个位置的情况:最小的总和是\((k + 1) * k / 2\),最大的情况对称。
倒着枚举每个数,只要能塞进去就塞。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
typedef pair<int,int> pii;
#define x first
#define y second
const int N = 505;
int ans[N];
int main()
{
int T;scanf("%d",&T);
while(T--)
{
int n,l,r,s;scanf("%d%d%d%d",&n,&l,&r,&s);
forn(i,1,n) ans[i] = 0;
int k = r - l + 1;
forr(i,1,n)
{
if(k > 0 && k * (2 * i + 1 - k) / 2 >= s && s - i >= k * (k - 1) / 2)
{
ans[l + k - 1] = i;
--k;
s -= i;
}
}
if(k)
{
puts("-1");
continue;
}
set<int> st;forn(i,l,r) st.insert(ans[i]);
int ga = 1;while(st.count(ga)) ga++;
forn(i,1,n)
{
if(ans[i]) continue;
ans[i] = ga;
st.insert(ga);
while(st.count(ga)) ++ga;
}
forn(i,1,n) printf("%d ",ans[i]);
puts("");
}
return 0;
}
F. Education
显然枚举答案:考虑最终停留在的位置。维护当前手上的钱以及为了走到这个位置已经度过了多少天数。更新答案即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
typedef pair<int,int> pii;
#define x first
#define y second
const int N = 2e5+7;
ll a[N],b[N];
int main()
{
int T;scanf("%d",&T);
while(T--)
{
ll n,c;scanf("%lld%lld",&n,&c);
forn(i,1,n) scanf("%lld",&a[i]);
forn(i,1,n - 1) scanf("%lld",&b[i]);
ll have = 0,res = 1e18,cur = 0;
forn(i,1,n)
{
res = min(res,(c - have + a[i] - 1) / a[i] + cur);
ll need = (b[i] - have + a[i] - 1) / a[i];
have += a[i] * need - b[i];cur += need + 1;
}
printf("%lld\n",res);
}
return 0;
}
G. Short Task
显然线性筛,考虑线性筛怎么求因数和:
-
对于\(p\in primes\),显然有\(d[p] = p + 1\).
-
对于\(i\),若\(i\%primes[j] == 0\)说明\(primes[j]\)不是\(i\)的最小因子,把因数和公式展开后可以得到结论:\(d[i * primes[j]] = d[i] * (primes[j] + 1)\)
-
若\(i\%pirmes[j] != 0\)说明\(primes[j]\)是\(i\)的最小因子,考虑维护每个数对应的最小质因子的在约数和中的贡献:即\(1+p+p^2+...p^{w_1}\),其中\(p\)是\(i\)的最小质因子。则\(d[i * primes[j]] = d[i] / minp[i] * minp[i * primes[j]]\).
-
维护\(minp\)部分:质数显然,若\(primes[j]\)不是\(i\)的最小质因子,那么\(minp[i * primes[j]] = primes[j] + 1\).否则\(minp[i * primes[j]] = minp[i] * primes[j] + 1\).
最后将还在范围内的答案计入即可。由于\(n \leq d(n) \leq 1e7\)所以筛到1e7即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
typedef pair<int,int> pii;
#define x first
#define y second
const int N = 1e7+7;
int primes[N],cnt,ans[N];
ll minp[N],dsum[N];
bool st[N];
void init()
{
dsum[1] = 1;
for(int i = 2;i < N;++i)
{
if(!st[i]) primes[cnt++] = i,dsum[i] = i + 1,minp[i] = i + 1;
for(int j = 0;j < cnt && 1ll*primes[j] * i < N;++j)
{
st[primes[j] * i] = 1;
if(i % primes[j]) dsum[i * primes[j]] = dsum[i] * (primes[j] + 1),minp[i * primes[j]] = primes[j] + 1;
else
{
minp[i * primes[j]] = minp[i] * primes[j] + 1;
assert(minp[i] != 0);
dsum[i * primes[j]] = dsum[i] / minp[i] * minp[i * primes[j]];
break;
}
}
}
forn(i,1,N - 1) if(dsum[i] < N && !ans[dsum[i]]) ans[dsum[i]] = i;
}
int main()
{
init();
int T;scanf("%d",&T);
while(T--)
{
int n;scanf("%d",&n);
printf("%d\n",ans[n] == 0 ? -1 : ans[n]);
}
return 0;
}