你最愿意做的哪件事,才是你的天赋所在

0%

牛客多校10题解报告

B

题目链接

B

思路

观察到S(n)=S(n-2)S(n-3)S(n-2),按照位置和长度进行搜索,因为只有1e12长度,先前缀处理出这个长度,就可以搜索了。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll md = 1e12+20;
ll f[501];
string s[5];
int n;
ll k;
void dfs(ll pos,int len,int num)
{
if(num<=3)
{
cout<<s[num].substr(pos,len);
return;
}
if(num>56)
{
dfs(pos,len,56);
return ;
}
ll len1=f[num-2],len2=f[num-2]+f[num-3];
if(pos+len<len1)
{
dfs(pos,len,num-2);
}
else if(pos<=len1&&pos+len>=len1)
{
if(pos+len>=len2)
{
dfs(pos,10,num-2);
dfs(0,pos-len1+len,num-3);
dfs(0,pos-len2+len,num-2);
}
else
{
dfs(pos,10,num-2);
dfs(0,pos-len1+len,num-3);
}
}
else if(pos+len<=len2)
{
dfs(pos-len1,len,num-3);
}
else if(pos<len2&&pos+len>=len2)
{
dfs(pos-len1,10,num-3);
dfs(0,pos-len2+len,num-2);
}
else if(pos>=len2)
{
dfs(pos-len2,len,num-2);
}
}
int main()
{
f[1]=6;
f[2]=7;
bool ok =false;
for(int i=3;i<=500;i++)
{
f[i]=(f[i-1]+f[i-2])%md;
}
for(int i=56;i<=500;i++)f[i]+=md;
int n;
scanf("%d",&n);
s[1]="COFFEE";
s[2]="CHICKEN";
s[3]="COFFEECHICKEN";
int a[34];
/*for(int i=1;i<=500;i++)
{ printf("i:%d ",i);
dfs(i-1,10,499);
printf("\n");
}*/
for(int i=0;i<n;i++)
{
ll x,y;
cin>>x>>k;
dfs(k-1,10,x);
printf("\n");
}
}

D

题目链接

D

思路

是一道EXCRT的板子题,但是需要用__int128来维护,打比赛的时候过了%75样例,代码不规范的原因。
具体的思路在这篇博客中说的很清楚了
中国剩余定理

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include<bits/stdc++.h>
using namespace std;
#define ll __int128
long long AK[105],AC[105];
long long m;
int n;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0){x=1;y=0;return a;}
ll gcd = exgcd(b,a%b,x,y);
ll temp = x;
x=y;
y=temp-a/b*y;
return gcd;
}
ll excrt()
{
ll a=AK[0],b=AC[0];
ll M=a,sum=b;
int ok=0;
int ok1=0;
for(int i=1;i<n;i++)
{
ll x,y;
a=AK[i],b=AC[i];
b=((b-sum)%a+a)%a;
ll gcd = exgcd(M,a,x,y);
if(b%gcd)ok=-1;
x=x*(b/gcd)%(a/gcd);
x=(x+a)%(a/gcd);
sum+=x*M;
M=M/gcd*a;
if(sum>m)
{
ok1=1;
}
}
if(ok)puts("he was definitely lying");
else if(ok1==1||sum>m) puts("he was probably lying");
else return printf("%lld\n",(long long)sum);
}
int main()
{
scanf("%d %lld",&n,&m);
for(int i=0;i<n;i++)scanf("%lld %lld",&AK[i],&AC[i]);
excrt();
}

E

题目链接

E

思路

用分治的思想,第一象限关于主对角线对称,第二象限关于副对角线对称,然后2*2的可以轻易求出来。
得到一个点以及大小后,不断地往回推即可

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
using namespace std;
#define ll long long
ll a[1025][1025];
ll b[2][2]={{1,4},{2,3}};
const int maxn = 1e6+10;
struct node
{
ll x, y;
int cp;
}arr[maxn];
int check(ll x,ll y,int num)
{
ll k = 1<<num;
if(x<=k/2&&y<=k/2)return 1;
else if(x>=k/2&&y<=k/2)return 3;
else if(x<=k/2&&y>=k/2)return 2;
else return 4;
}
ll solve(ll x,ll y,int k)
{
ll num = 1<<k;
ll half = num/2;
if(k==1)return b[--x][--y];
int area = check(x,y,k);
if(area==1)
{
return solve(y,x,k-1);
}
else if(area==2)
{
y-=half;
return half*half*3+solve(half-y+1,half-x+1,k-1);
}
else if(area==3)
{
return half*half*1+solve(x-half,y,k-1);
}
else if(area==4)
{
return half*half*2+solve(x-half,y-half,k-1);
}
}
int cmp(node s,node t)
{
return s.cp<t.cp;
}
int main()
{
int n,k;
scanf("%d %d",&n,&k);
ll x,y;
for(int i=0;i<n;i++)
{
scanf("%lld %lld",&arr[i].x,&arr[i].y);
arr[i].cp=solve1(arr[i].x,arr[i].y,k);
}
sort(arr,arr+n,cmp);
for(int i=0;i<n;i++)
{
printf("%lld %lld\n",arr[i].x,arr[i].y);
}
}
-------------你最愿意做的哪件事才是你的天赋所在-------------