B Coffee Chicken
题意:给定S(1)=“COFFEE”,S(2)=“CHICKEN”,
S
(
n
)
=
S
(
n
−
2
)
+
S
(
n
−
1
)
S(n)=S(n-2)+S(n-1)
S(n)=S(n−2)+S(n−1),给定
n
、
k
n、k
n、k,请你输出
S
(
n
)
S(n)
S(n)中第
k
k
k个字符开始连续的10个字符
思路:递归搜索出k的位置,坑点是k最大是
1
0
12
10^{12}
1012,所以
s
(
n
)
s(n)
s(n)的长度尽管会爆longlong,但其实只需要记录
1
0
12
+
10
10^{12}+10
1012+10即可。递归搜索时如果是到了末尾,不到10个也不用搜
#include <iostream>
#include <string>
#define ll long long
using namespace std;
const ll maxn=1e5+5,INF=1e12+10;
int T,n;
string s1="COFFEE";
string s2="CHICKEN";
ll dp[505],k;
char recursion(int n,ll k)
{
if(n==1)
return s1[k-1];
if(n==2)
return s2[k-1];
if(k<=dp[n-2])
recursion(n-2,k);
else
recursion(n-1,k-dp[n-2]);
}
int main()
{
dp[1]=6,dp[2]=7;
for(int i=3;i<=500;i++)
{
dp[i]=dp[i-2]+dp[i-1];
dp[i]=min(dp[i],INF);
}
cin>>T;
while(T--)
{
cin>>n>>k;
for(ll i=k;i<k+10&&i<=dp[n];++i)
cout<<recursion(n,i);
cout<<"\n";
}
return 0;
}
D Han Xin and His Troops
题意:求解线性同余方程
思路:
x
≡
r
1
(
m
o
d
a
1
)
x\equiv r_1(mod\ a_1)
x≡r1(mod a1),
x
≡
r
2
(
m
o
d
a
2
)
x\equiv r_2(mod\ a_2)
x≡r2(mod a2),联立得到
a
1
k
1
+
r
1
=
a
2
k
2
+
r
2
a_1k_1+r_1=a_2k_2+r_2
a1k1+r1=a2k2+r2 移项得
a
1
k
1
−
a
2
k
2
=
r
2
−
r
1
a_1k_1-a_2k_2=r_2-r_1
a1k1−a2k2=r2−r1,得到
k
1
k_1
k1 的一个解
k
1
=
k
′
+
n
×
a
2
g
c
d
(
a
1
,
a
2
)
k_1=k'+\frac{n \times a_2}{gcd(a_1,a_2)}
k1=k′+gcd(a1,a2)n×a2 代回到
x
=
r
1
+
a
1
k
1
x=r_1+a_1k_1
x=r1+a1k1中,
x
=
r
1
+
a
1
(
k
′
+
n
×
a
2
g
c
d
(
a
1
,
a
2
)
)
x=r_1+a_1(k'+\frac{n \times a_2}{gcd(a_1,a_2)})
x=r1+a1(k′+gcd(a1,a2)n×a2),也就得到了
x
=
r
1
+
a
1
k
′
+
a
1
n
×
a
2
g
c
d
(
a
1
,
a
2
)
)
x=r_1+a_1k'+a_1\frac{n \times a_2}{gcd(a_1,a_2)})
x=r1+a1k′+a1gcd(a1,a2)n×a2) 即
x
≡
r
1
+
a
1
k
′
(
m
o
d
a
1
a
2
g
c
d
(
a
1
,
a
2
)
)
x\equiv r_1+a_1k' (mod\ \frac {a_1a_2}{gcd(a_1,a_2)})
x≡r1+a1k′(mod gcd(a1,a2)a1a2)
def exgcd(a,b):
if b==0:
return 1,0,a
y,x,q=exgcd(b,a%b)
y-=a//b*x
return x,y,q
def solve(n,a,r):
a1=a[1]
r1=r[1]
for i in range(2,n+1):
A=a1
B=a[i]
M=r[i]-r1;
X,Y,GCD=exgcd(A,B)
if M%GCD!=0:
return -1
b1=B//GCD
X=(X*M//GCD%b1+b1)%b1
r1=r1+a1*X
a1=a1*a[i]//GCD
return r1
if __name__ =="__main__":
n,m=map(int,input().split())
a=[0]*105
r=[0]*105
for i in range(1,n+1):
a[i],r[i]=map(int,input().split())
ans=solve(n,a,r)
if ans==-1:
print("he was definitely lying")
elif ans>m:
print("he was probably lying")
else:
print(ans)
E Hilbert Sort
题意:根据递归定义的希尔伯特曲线,给定n个该曲线上的坐标,按顺序输出
思路:对每个点递归计算它的权值。根据当前层的坐标是x,y,讨论出上层的坐标,上层其实就相当于把当前层分为四块的右下角,递归计算即可
#include <iostream>
#include <algorithm>
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define ll long long
using namespace std;
const int maxn=1e6+5,INF=0x3f3f3f3f;
const int mod=1e9+7;
int n,k;
struct Point
{
int x,y;
ll value;
bool operator<(const Point & b) const
{
return value<b.value;
}
}p[maxn];
ll recursion(int x,int y,int k)
{
if(k==0)
return 0;
ll kk=(1ll<<k);
ll value=kk*kk;
if(x<=kk/2&&y<=kk/2)
return recursion(y,x,k-1);
else if(x>kk/2&&y<=kk/2)
return recursion(x-kk/2,y,k-1)+value;
else if(x>kk/2&&y>kk/2)
return recursion(x-kk/2,y-kk/2,k-1)+value*2;
else if(x<=kk/2&&y>kk/2)
return recursion(kk-y+1,kk/2-x+1,k-1)+value*3;
}
int main()
{
cin>>n>>k;
for(int i=1;i<=n;++i)
{
cin>>p[i].x>>p[i].y;
p[i].value=recursion(p[i].x,p[i].y,k);
}
sort(p+1,p+1+n);
rep(i,1,n)
cout<<p[i].x<<" "<<p[i].y<<"\n";
return 0;
}
F Popping Balloons
题意:给定一个矩阵,矩阵的某些点上有气球,问你怎样选择横三行,竖三行,使得打掉的气球最多。其中三横三竖,相邻两行之间的距离为r
思路:将三行三竖的气球数量,都缩减为一个点,二维数组v[i]表示的是 i i i 这一行,代表的三行中所有气球的列坐标y,把所有竖三行的数量,放进multiset中,每次枚举一个行坐标的时候,就把这个行,代表的三行的所有气球都在列坐标中取消掉。然后取列坐标代表的三列中的最大值。可以使用multiset取,也可以使用线段树取最大值。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <cstring>
#include <string>
#include <cmath>
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b) memset(a,b,sizeof(a))
#define mp make_pair
#define ll long long
#define pb push_back
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ls (rt<<1)
#define rs ((rt<<1)|1)
#define isZero(d) (abs(d) < 1e-8)
using namespace std;
const int maxn=1e5+5,INF=0x3f3f3f3f;
const int mod=1e9+7;
int n,r,x,y;
vector<int> v[maxn*3];
vector<int> cnt(maxn*3,0);
multiset<int> s;
void Delete(int k)
{
auto p=s.find(cnt[k]);
s.erase(p);
cnt[k]--;
s.insert(cnt[k]);
}
void Add(int k)
{
auto p=s.find(cnt[k]);
s.erase(p);
cnt[k]++;
s.insert(cnt[k]);
}
int main()
{
cin>>n>>r;
for(int i=1;i<=n;++i)
{
cin>>x>>y;
x+=r;
y+=r;
v[x-r].pb(y);
v[x].pb(y);
v[x+r].pb(y);
cnt[y-r]++;
cnt[y]++;
cnt[y+r]++;
}
for(int i=0;i<maxn+2*r;++i)
s.insert(cnt[i]);
int ans=0;
for(int i=r;i<maxn;++i)
{
for(auto it: v[i])
{
Delete(it-r);
Delete(it);
Delete(it+r);
}
auto p=s.rbegin();
int temp=(int)v[i].size()+(*p);
ans=max(ans,temp);
for(auto it: v[i])
{
Add(it-r);
Add(it);
Add(it+r);
}
}
cout<<ans<<"\n";
return 0;
}