2021/2/7训练赛
Problem.A August
题解
不难发现上半部分是个半径为
a
a
a的圆,下半部分利用割补小正方形的方法得出等价于一个长为
2
a
2a
2a,宽为
2
b
2b
2b的长方形。
比赛时没有发现,不过队友看出下半部分面积应该是个关于
a
a
a和
b
b
b的表达式,并且很好算,用答案减去圆的面积反推出面积为
4
a
b
4ab
4ab。
代码
#include <bits/stdc++.h>
#define PI atan(1.0)*4
#define rp(i,s,t) for (register int i = (s); i <= (t); i++)
#define RP(i,t,s) for (register int i = (t); i >= (s); i--)
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define m_p make_pair
#define p_b push_back
#define ins insert
#define era erase
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f3f3f3f
#define dg if(debug)
#define pY puts("YES")
#define pN puts("NO")
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n";
#define outval2(a,b) cout << "Debuging...|" << #a << ": " << a <<"\t"<< #b << ": " << b << "\n";
#define outval3(a,b,c) cout << "Debuging...|" << #a << ": " << a <<"\t"<< #b << ": " << b <<"\t"<< #c << ": " << c << "\n";
using namespace std;
int debug = 0;
ll gcd(ll a,ll b){
return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b){
return a/gcd(a,b)*b;
}
inline int read(){
int s=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
s=s*10+ch-'0';
ch=getchar();
}
return s*f;
}
void solve(){
int a=read(),b=read();
double ans=PI*a*a;
printf("%.8f\n",ans+4.0*a*b);
}
int main(){
//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifdef ONLINE_JUDGE
#else
freopen("in.txt", "r", stdin);
//debug = 1;
#endif
//time_t beg, end;
//if(debug) beg = clock();
int T=read();
while(T--) solve();
/*
if(debug) {
end = clock();
printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);
}
*/
return 0;
}
Problem.C Cornelia Street
题解
比赛时感觉时间复杂度不是特别好确定,而且极端数据不是特别好构造,就写了一法暴力枚举
A
A
A串长度的做法,交之前测了几发大数据都过了,就交了,一发A。
时间复杂度好像类似于调和级数。
代码
#include <bits/stdc++.h>
#define PI atan(1.0)*4
#define rp(i,s,t) for (register int i = (s); i <= (t); i++)
#define RP(i,t,s) for (register int i = (t); i >= (s); i--)
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define m_p make_pair
#define p_b push_back
#define ins insert
#define era erase
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f3f3f3f
#define dg if(debug)
#define pY puts("YES")
#define pN puts("NO")
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n";
#define outval2(a,b) cout << "Debuging...|" << #a << ": " << a <<"\t"<< #b << ": " << b << "\n";
#define outval3(a,b,c) cout << "Debuging...|" << #a << ": " << a <<"\t"<< #b << ": " << b <<"\t"<< #c << ": " << c << "\n";
using namespace std;
int debug = 0;
ll gcd(ll a,ll b){
return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b){
return a/gcd(a,b)*b;
}
inline int read(){
int s=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
s=s*10+ch-'0';
ch=getchar();
}
return s*f;
}
const int N = 1e5+7;
void solve(){
string s;cin>>s;
int len=s.size();
rp(l,1,len){
string pa="";
rp(i,0,l-1) pa+=s[i];
string pb="";
int f=1;
int ff=0;
rp(i,l,len-1){
int num=1;
string t="";t+=s[i];
while(i+1<len&&num<l) i++,t+=s[i],num++;
if(t==pa){
if(f==2) f=3;
}
else if(pb.size()==0&&f==1){
pb=t;f=2;
}
else if(t==pb&&f==2) continue;
else {
if(f==3){
if(i==len-1){
string tt=pa.substr(0,num);
if(tt!=t){
ff=1;
break;
}
}
else{
ff=1;
break;
}
}
else{
ff=1;
break;
}
}
}
// outval2(l,ff);
if(!ff&&f!=1){
cout<<pa<<" "<<pb<<endl;
break;
}
}
}
int main(){
//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
solve();
return 0;
}
Problem.F False God
队友写的:
请参考题解
Problem.G Goodbye
题解
手推几个样例可以发现规律:
首先对
n
n
n进行唯一分解,并维护出最大的两个质因子。
1.当
n
n
n为质数或者
1
1
1时,输出
0
0
0。
2.当质因子个数小于等于2时,输出
−
1
-1
−1。
3.否则答案就是这两个最大的质因子的乘积。
原因:首先为了保证
C
h
i
n
o
Chino
Chino必胜,只能给
D
a
v
i
d
David
David剩下两个质因子的乘积。
而又需要保证
C
h
i
n
o
Chino
Chino的第一轮取的值最大,根据贪心的原则选取最大的两个质因子的乘积是最优策略。
代码
// #pragma GCC optimize(2)
#include <bits/stdc++.h>
#define m_p make_pair
#define p_i pair<int, int>
#define _for(i, a) for(int i = 0, lennn = (a); i < lennn; ++i)
#define _rep(i, a, b) for(int i = (a), lennn = (b); i <= lennn; ++i)
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n"
#define mem(a, b) memset(a, b, sizeof(a))
#define mem0(a) memset(a, 0, sizeof(a))
#define fil(a, b) fill(a.begin(), a.end(), b);
#define scl(x) scanf("%lld", &x)
#define sc(x) scanf("%d", &x)
#define pf(x) printf("%d\n", x)
#define pfl(x) printf("%lld\n", x)
#define abs(x) ((x) > 0 ? (x) : -(x))
#define PI acos(-1)
#define lowbit(x) (x & (-x))
#define dg if(debug)
#define nl(i, n) (i == n - 1 ? "\n":" ")
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
typedef long long LL;
// typedef __int128 LL;
typedef unsigned long long ULL;
const int maxn = 100005;
const int maxm = 1000005;
const int maxp = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-8;
const double e = 2.718281828;
int debug = 0;
inline int read() {
int x(0), f(1); char ch(getchar());
while (ch<'0' || ch>'9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
struct poi {
};
int n;
vector<int> arr;
int vis[1000006];
void doit(int maxnum) {
for(int i = 2; i <= maxnum; ++i) {
if(!vis[i]) arr.push_back(i);
for(int j = 0; j < arr.size() && arr[j] * i <= maxnum; ++j) {
vis[arr[j] * i] = 1;
if(i % arr[j] == 0) break;
}
}
}
void init() {
}
void sol() {
init();
if(n == 1) {
printf("0\n");
return;
}
int a = 0, b = 0;
int x = n;
for(int i = 0; i < arr.size() && arr[i] <= x; ++i) {
// dg outval(arr[i]);
while(x % arr[i] == 0) {
if(arr[i] > a) {
b = a;
a = arr[i];
}
else if(arr[i] > b) b = arr[i];
x /= arr[i];
}
}
if(a == n) {
printf("0\n");
return;
}
if(b == 0 || n == a * b) {
printf("-1\n");
return;
}
// dg outval(a), outval(b);
printf("%d\n", a * b);
}
int main() {
//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
debug = 1;
#endif
time_t beg, end;
if(debug) beg = clock();
doit(100000);
int T = read();
_for(i, T) {
n = read();
sol();
}
// _rep(i, 1, 20) {
// n = i;
// sol();
// }
if(debug) {
end = clock();
printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);
}
return 0;
}
Problem.H Hate That You Know Me
题解
这个题首先需要知道两个结论:
1.约数个数和等于数论分块和
即
∑
i
=
1
n
σ
0
(
i
)
=
∑
i
=
1
n
⌊
n
i
⌋
\sum_{i=1}^n\sigma_0(i)=\sum_{i=1}^n\lfloor\frac{n}{i}\rfloor
∑i=1nσ0(i)=∑i=1n⌊in⌋。
2.约数和等于数论分块和的变形
即
∑
i
=
1
n
σ
1
(
i
)
=
∑
i
=
1
n
i
×
⌊
n
i
⌋
\sum_{i=1}^n\sigma_1(i)=\sum_{i=1}^ni\times\lfloor\frac{n}{i}\rfloor
∑i=1nσ1(i)=∑i=1ni×⌊in⌋。
那么我们不难得出约数平方和以及约数立方和的公式:
约数平方和
即
∑
i
=
1
n
σ
2
(
i
)
=
∑
i
=
1
n
i
2
×
⌊
n
i
⌋
\sum_{i=1}^n\sigma_2(i)=\sum_{i=1}^ni^{2}\times\lfloor\frac{n}{i}\rfloor
∑i=1nσ2(i)=∑i=1ni2×⌊in⌋。
约数立方和
即
∑
i
=
1
n
σ
3
(
i
)
=
∑
i
=
1
n
i
3
×
⌊
n
i
⌋
\sum_{i=1}^n\sigma_3(i)=\sum_{i=1}^ni^{3}\times\lfloor\frac{n}{i}\rfloor
∑i=1nσ3(i)=∑i=1ni3×⌊in⌋。
那么把公式转换以后不难发现第二个公式可以直接用数论分块求出答案。
对数论分块不懂的话请参考该链接。
题目中给的取余是自然溢出,我们直接用unsigned long long 维护答案即可。
trick: 注意要保证能够整除再进行除运算,否则直接用下取整会使得答案偏小。
代码
#include <bits/stdc++.h>
#define PI atan(1.0)*4
#define rp(i,s,t) for (register int i = (s); i <= (t); i++)
#define RP(i,t,s) for (register int i = (t); i >= (s); i--)
#define sc(x) scanf("%d",&x)
#define ll unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define m_p make_pair
#define p_b push_back
#define ins insert
#define era erase
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f3f3f3f
#define dg if(debug)
#define pY puts("YES")
#define pN puts("NO")
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n";
#define outval2(a,b) cout << "Debuging...|" << #a << ": " << a <<"\t"<< #b << ": " << b << "\n";
#define outval3(a,b,c) cout << "Debuging...|" << #a << ": " << a <<"\t"<< #b << ": " << b <<"\t"<< #c << ": " << c << "\n";
using namespace std;
int debug = 0;
ll gcd(ll a,ll b){
return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b){
return a/gcd(a,b)*b;
}
inline int read(){
int s=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
s=s*10+ch-'0';
ch=getchar();
}
return s*f;
}
ll f1(ll x){
ll a=x,b=x+1;
if(a%2==0) a/=2;
else b/=2;
return a*b;
}
ll f2(ll x){
ll a=x,b=x+1,c=2*x+1;
if(a%2==0) a/=2;
else b/=2;
if(a%3==0) a/=3;
else if(b%3==0) b/=3;
else if(c%3==0) c/=3;
return a*b*c;
}
ll f3(ll x){
ll a=x,b=x+1;
if(a%2==0) a/=2;
else b/=2;
return a*b*a*b;
}
ll calc(ll l,ll r,ll op){
if(op==0) return r-l+1ll;
else if(op==1) return f1(r)-f1(l-1);
else if(op==2) return f2(r)-f2(l-1);
else return f3(r)-f3(l-1);
}
void solve(){
ll a,b,n;cin>>a>>b>>n;
if(a==b){
puts("0");
return ;
}
ll ans1=0;
for(ll l = 1, r = 0; l <= n; l=r+1) {
r = n / (n / l);
ans1+=(n/l)*calc(l,r,a);
}
ll ans2=0;
for(ll l = 1, r = 0; l <= n; l=r+1) {
r = n / (n / l);
ans2+=(n/l)*calc(l,r,b);
// outval3(l,r,calc(l,r,b));
}
// outval2(ans1,ans2);
cout<<(ans1^ans2)<<endl;
}
int main(){
//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifdef ONLINE_JUDGE
#else
freopen("in.txt", "r", stdin);
//debug = 1;
#endif
//time_t beg, end;
//if(debug) beg = clock();
int T=1;
while(T--) solve();
/*
if(debug) {
end = clock();
printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);
}
*/
return 0;
}
Problem.L Let’s Get Married
题解
可以发现是按照
b
f
s
bfs
bfs的顺序进行放的。
那么我们对于每次的
1
1
1操作,二分枚举得出
i
d
id
id的层数,并可以找规律得出具体坐标。
对于每次的
2
2
2操作,也可以通过找规律得出其编号。
代码
// #pragma GCC optimize(2)
#include <bits/stdc++.h>
#define m_p make_pair
#define p_i pair<LL, LL>
#define _for(i, a) for(LL i = 0, lennn = (a); i < lennn; ++i)
#define _rep(i, a, b) for(LL i = (a), lennn = (b); i <= lennn; ++i)
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n"
#define mem(a, b) memset(a, b, sizeof(a))
#define mem0(a) memset(a, 0, sizeof(a))
#define fil(a, b) fill(a.begin(), a.end(), b);
// #define scl(x) scanf("%lld", &x)
// #define sc(x) scanf("%d", &x)
#define pf(x) printf("%d\n", x)
#define pfl(x) printf("%lld\n", x)
#define abs(x) ((x) > 0 ? (x) : -(x))
#define PI acos(-1)
#define lowbit(x) (x & (-x))
#define dg if(debug)
#define nl(i, n) (i == n - 1 ? "\n":" ")
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
typedef long long LL;
// typedef __int128 LL;
typedef unsigned long long ULL;
const LL maxn = 100005;
const LL maxm = 1000005;
const LL maxp = 30;
const LL inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL mod = 1000000007;
const double eps = 1e-8;
const double e = 2.718281828;
LL debug = 0;
inline LL read() {
LL x(0), f(1); char ch(getchar());
while (ch<'0' || ch>'9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
LL n;
inline void print(LL x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9)
print(x / 10);
putchar(x % 10 + '0');
}
pair< LL, LL > getV(LL id) {
if(id <= 4) return m_p(0, 0);
LL l = 1, r = 1e9, ans = l;
while(l <= r) {
LL mid = (l + r) /2;
if((4 * mid + 4) * mid / 2 <= id) {
ans = mid;
l = mid + 1;
}
else r = mid - 1;
}
return m_p(ans, (4 * ans + 4) * ans / 2);
}
int main() {
// ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
// debug = 1;
#endif
n = read();
LL nx = 0, ny = 0;
_for(i, n) {
LL op = read(), x, y;
if(op == 1) {
LL id = read();
if(id == 0) {
x = 0, y = 0;
}
else {
pair<LL, LL> t = getV(id);
dg outval(t.first), outval(t.second);
if(id - t.second <= 2 * t.first + 1) {
if((id - t.second) == 0) {
x = 0, y = t.first + 1;
}
else if((id - t.second)%2==1LL) {
x = -(id - t.second) / 2, y = t.first + 1 - (id - t.second) / 2;
}
else {
x = (id - t.second) / 2, y = t.first + 1 - (id - t.second) / 2;
}
}
else if((id - t.second) <= 2 * t.first + 1 + t.first + 2) {
LL nol = t.second + 2 * t.first + 2;
x = t.first + 1 - (id - nol), y = -(id - nol);
}
else {
LL nod = t.second + 2 * t.first + 2 + t.first + 1;
x = -(id - nod), y = -(t.first + 1 - (id - nod));
}
}
dg printf("x:%lld\ty:%lld\n", x, y);
print(x - nx);
printf(" ");
print(y - ny);
printf("\n");
}
else {
x = read(), y = read();
if(x == 0 && y == 0) {
printf("0\n");
}
else {
LL tf = abs(x) + abs(y) - 1;
LL ts = (4 * tf + 4) * tf / 2;
if(x == 0 && y > 0) print(ts + 1), printf("\n");
else if(x > 0 && y > 0) {
print(ts + 2 * x); printf("\n");
}
else if(x < 0 && y > 0) {
print(ts + 1 - 2 * x); printf("\n");
}
else if(x >= 0 && y <= 0) {
LL nol = ts + 2 * tf + 2;
print(nol - y); printf("\n");
}
else {
LL nod = ts + 2 * tf + 2 + tf + 1;
print(nod - x); printf("\n");
}
}
}
nx = x, ny = y;
}
return 0;
}