TZOJ 挑战题库随机训练04

点击题号跳转

A5245 B3012 C3927 D1363 E3756

F1418 G4177 H5114 I3613 J4140

A.C++实验:日期相减回到顶部

题意

给一个日期求前num天的日期

题解

每次-1天,判断一下闰年就行,复杂度O(num)

需要重载+号和输出<<号

代码

 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 struct Date{
 7     int y,m,d;
 8     Date(int _y=0,int _m=0,int _d=0):y(_y),m(_m),d(_d){}
 9 };
10 Date operator-(Date a,int num){
11     while(num--){
12         if(a.d>1)a.d--;
13         else if(a.d==1){
14             if(a.m>1){
15                 if(a.m==2||a.m==4||a.m==6||a.m==8||a.m==9||a.m==11){
16                     a.m--;a.d=31;
17                 }else if(a.m==3){
18                     if(a.y%400==0||(a.y%4==0&&a.y%100!=0)){
19                         a.m--;a.d=29;
20                     }else{
21                         a.m--;a.d=28;
22                     }
23                 }else{
24                     a.m--;a.d=30;
25                 }
26             }
27             else if(a.m==1){
28                 a.y--;a.m=12;a.d=31;
29             }
30         }
31     }
32     return a;
33 }
34 ostream& operator<<(ostream &out,Date s)
35 {
36     cout<<s.y<<"-"<<s.m<<"-"<<s.d;
37     return out;
38 }
A

B.Fibnacci Numbers回到顶部

题意

f[1]=1,f[2]=2,f[i]=f[i-1]+f[i-2]

s[n]=Σf[i]^2

给定a,n,x,1 ≤ a ≤ 100000000; 1 ≤ x ≤ 1000000000; 2 ≤ n ≤ 100000000

求ans=(a^s[x])%n

题解

找规律得到s[x]=f[x]*f[x+1]-1,式子变成ans=(a^(f[x]*f[x+1]-1))%n

模数不是质数,采用广义欧拉降幂,式子变成

然后需要求出(f[n]*f[n+1]-1)%phi,可以采用矩阵快速幂

构造矩阵[1 1,0 0]*([1 1,1 0]^x)%phi,矩阵快速幂求出[1 1 1 0]^x%phi,最后乘上初始矩阵[1 1 0 0],得到f[x]和f[x+1]

最后通过快速幂求出答案,复杂度O(8logxlogx)

PS:矩阵快速幂%phi不是%n,被坑了一下

UPD:有人指出代码中广义欧拉降幂不够严谨,于是我改正了,感谢zzl和wff

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define LL long long
 5 LL GetPhi(LL n)
 6 {
 7     LL m=sqrt(n+0.5);
 8     LL ans=n;
 9     for(int i=2;i<=m;++i)
10         if(n%i==0){
11         ans=ans/i*(i-1);
12         while(n%i==0)n/=i;
13     }
14     if(n>1)ans=ans/n*(n-1);
15     return ans;
16 }
17 LL MD,phi;
18 struct mat{
19     LL a[2][2];
20     mat(){
21         memset(a,0,sizeof a);
22     }
23     mat operator*(const mat &b)const{
24         mat c;
25         for(int i=0;i<2;i++)
26             for(int j=0;j<2;j++)
27                 for(int k=0;k<2;k++)
28                     c.a[i][j]=(c.a[i][j]+a[i][k]*b.a[k][j]%phi)%phi;
29         return c;
30     }
31 };
32 mat quick(mat a,LL b){
33     mat ans;
34     for(int i=0;i<2;i++)ans.a[i][i]=1;
35     while(b){
36         if(b&1)ans=ans*a;
37         a=a*a;
38         b>>=1;
39     }
40     return ans;
41 }
42 LL quick_LL(LL a,LL b){
43     LL ans=1;
44     while(b){
45         if(b&1)ans=ans*a%MD;
46         a=a*a%MD;
47         b>>=1;
48     }
49     return ans;
50 }
51 int main(){
52     LL a,x;
53     while(scanf("%lld%lld%lld",&a,&x,&MD)!=EOF,a||x||MD){
54         LL val=0;
55         phi=GetPhi(MD);
56         mat ans;
57         ans.a[0][0]=ans.a[1][0]=ans.a[0][1]=1;
58         ans=quick(ans,x);
59         mat A;
60         A.a[0][0]=A.a[0][1]=1;
61         ans=A*ans;
62         //printf("%lld %lld\n",ans.a[0][0],ans.a[0][1]);
63         val=(ans.a[0][0]*ans.a[0][1]%phi-1+phi)%phi;
64         printf("%lld\n",quick_LL(a,val%phi+phi)%MD);
65     }
66     return 0;
67 }
B 不严谨的代码
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define LL long long
 5 LL GetPhi(LL n)
 6 {
 7     LL m=sqrt(n+0.5);
 8     LL ans=n;
 9     for(int i=2;i<=m;++i)
10         if(n%i==0){
11         ans=ans/i*(i-1);
12         while(n%i==0)n/=i;
13     }
14     if(n>1)ans=ans/n*(n-1);
15     return ans;
16 }
17 LL MD,phi;
18 struct mat{
19     LL a[2][2];
20     mat(){
21         memset(a,0,sizeof a);
22     }
23     mat operator*(const mat &b)const{
24         mat c;
25         for(int i=0;i<2;i++)
26             for(int j=0;j<2;j++)
27                 for(int k=0;k<2;k++)
28                     c.a[i][j]=(c.a[i][j]+a[i][k]*b.a[k][j]%phi)%phi;
29         return c;
30     }
31 };
32 mat quick(mat a,LL b){
33     mat ans;
34     for(int i=0;i<2;i++)ans.a[i][i]=1;
35     while(b){
36         if(b&1)ans=ans*a;
37         a=a*a;
38         b>>=1;
39     }
40     return ans;
41 }
42 LL quick_LL(LL a,LL b){
43     LL ans=1;
44     while(b){
45         if(b&1)ans=ans*a%MD;
46         a=a*a%MD;
47         b>>=1;
48     }
49     return ans;
50 }
51 int main(){
52     LL a,x;
53     LL f[21]={1,1};
54     for(int i=2;i<21;i++)f[i]=f[i-1]+f[i-2];
55     //printf("%lld\n",f[19]*f[20]);
56     while(scanf("%lld%lld%lld",&a,&x,&MD)!=EOF,a||x||MD){
57         LL gcd=__gcd(a,MD);
58         if(gcd!=1&&x<20&&f[x]*f[x+1]-1<phi){
59             printf("%lld\n",quick_LL(a,f[x]*f[x+1]-1)%MD);
60         }else{
61             phi=GetPhi(MD);
62             mat ans;ans.a[0][0]=ans.a[1][0]=ans.a[0][1]=1;
63             ans=quick(ans,x);
64             mat A;A.a[0][0]=A.a[0][1]=1;
65             ans=A*ans;
66             //printf("%lld %lld\n",ans.a[0][0],ans.a[0][1]);
67             LL val=(ans.a[0][0]*ans.a[0][1]%phi-1+phi)%phi;
68             printf("%lld\n",quick_LL(a,val%phi+phi)%MD);
69         }
70     }
71     return 0;
72 }
B 严谨的代码 pointed by zzl and wff

C.Circular Sequence回到顶部

题意

n([1,10^5])个数围成一个环,求最大子段和

题解

做过一个简单版的,排成1排的最大字段和

可以求出简单版的最大字段和

如果我们把n个数拉长变成2*n

另一种情况就是跨过n的最大字段和,那我们只需要dp求出到右端点r的最大子段和

dp[i]=max(dp[i-1],PreSum+a[i])

然后枚举左端点,求出右端点,求出[l,n]的和+dp[l]即可,复杂度O(n)

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define LL long long
 5 const int N=1e5+5;
 6 LL a[N],pre[N];
 7 int main(){
 8     int t,n;
 9     scanf("%d",&t);
10     while(t--){
11         scanf("%d",&n);
12         LL preSum=0,maxN=-1e9;
13         for(int i=1;i<=n;i++){
14             scanf("%lld",&a[i]);
15             maxN=max(maxN,a[i]);
16             preSum+=a[i];
17             pre[i]=max(pre[i-1],preSum);
18         }
19         LL sum=0,ans=0,f=0;
20         for(int i=1;i<=n;i++){
21             sum+=a[i];
22             if(a[i]>=0)f=1;
23             if(sum<0)sum=0;
24             ans=max(ans,sum);
25             if(i<n){
26                 preSum-=a[i];
27                 ans=max(ans,preSum+pre[i]);
28             }
29         }
30         if(f)printf("%lld\n",ans);
31         else printf("%lld\n",maxN);
32     }
33     return 0;
34 }
C

D.Destroy the Well of Life回到顶部

题意

n([1,250])口井,需要摧毁第n口井,wi,li,pi代表初始容量wi,最大容量li,摧毁花费pi(wi<=li, 0<=wi, li, pi <=20000)

当一口井wi>li,井自动摧毁

直接摧毁一口井,花费pi

当第i口井被摧毁,所有水自动加入i+1口井

题解

n只有250,直接模拟一下就行了,复杂度O(n^2)

感谢zzl提供复杂度O(nlogn)的做法,做法是维护一个优先队列,优先队列存x和y,x代表要使第i口井不花费pi摧毁的水量,y代表摧毁第i口井的代价

PS:原来的题n=10^5,卡了挺久的,最后测了一下数据发现n只有250

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N=250;
 5 int w[N],l[N],p[N];
 6 int main(){
 7     int t,ca=1;
 8     scanf("%d",&t);
 9     while(t--){
10         int n;
11         scanf("%d",&n);
12         for(int i=0;i<n;i++){
13             scanf("%d%d%d",&w[i],&l[i],&p[i]);
14         }
15         int sum=p[n-1];
16         for(int i=0;i<n;i++){
17             int ans=0,ma=0;
18             for(int j=i;j<n;j++){
19                 ma+=w[j];
20                 if(ma<=l[j])ans+=p[j];
21             }
22             sum=min(ans,sum);
23         }
24         printf("Case %d: Need to use %d mana points.\n",ca++,sum);
25     }
26     return 0;
27 }
D O(n^2)
 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int N=1e5+5;
 5 struct P {
 6     ll x,y;
 7     bool operator <(const P &t)const {
 8         return x>t.x;
 9     }
10 };
11 ll w[N],l[N],p[N],f[N];
12 int main() {
13     //freopen("in.txt","r",stdin);
14     int T,n,o=0;
15     scanf("%d",&T);
16     while(T--) {
17         scanf("%d",&n);
18         for(int i=1;i<=n;i++) {
19             scanf("%lld%lld%lld",&w[i],&l[i],&p[i]);
20         }
21         f[n]=0;
22         priority_queue<P> qu;
23         qu.push({l[n]-w[n],p[n]});
24         ll sum=p[n],s=0;
25         for(int i=n-1;i>=1;i--) {
26             s+=w[i];
27             while(!qu.empty()) {
28                 if(s>qu.top().x) sum-=qu.top().y,qu.pop();
29                 else break;
30             }
31             f[i]=sum;
32             sum+=p[i],qu.push({l[i]-w[i]+s,p[i]});
33         }
34         ll ans=1e18;
35         for(int i=1;i<=n;i++) {
36             ans=min(ans,f[i]+p[i]);
37         }
38         printf("Case %d: Need to use %lld mana points.\n",++o,ans);
39     }
40     return 0;
41 }
D O(nlogn) by zzl

E.Just multiply it回到顶部

题意

求n([1,10^6])的所有因子乘积%10007

题解

枚举到根号n求出所有因子,需要注意n是不是完全平方数,复杂度O(sqrt(n))

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main(){
 5     int t;
 6     scanf("%d",&t);
 7     while(t--){
 8         int n;
 9         scanf("%d",&n);
10         int b=sqrt(n+0.5);
11         int ans=1,p=10007;
12         if(n==b*b)ans=b,b--;
13         for(int i=2;i<=b;i++)
14             if(n%i==0)
15                 ans=ans*1LL*i%p*(n/i)%p;
16         printf("%d\n",ans);
17     }
18     return 0;
19 }
E

F.复习时间回到顶部

题意

复习后一门课的效率为前一门课之间的难度差的平方,而复习第一门课的效率为100和这门课的难度差的平方。xhd这学期选了n门课,但是一晚上他最多只能复习m门课,请问他复习单独一门课

的最高效率值是多少

题解

求出最小值,max(100-最小值的平方,最大值-最小值的平方),复杂度O(1)

PS:看不懂题意怎么办,猜啊

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main(){
 5     int t;
 6     scanf("%d",&t);
 7     while(t--){
 8         int n,m,x,minn=101,maxx=0;
 9         scanf("%d%d",&n,&m);
10         for(int i=1;i<=n;i++){
11             scanf("%d",&x);
12             minn=min(minn,x);
13             maxx=max(maxx,x);
14         }
15         printf("%d\n",max((100-minn)*(100-minn),(maxx-minn)*(maxx-minn)));
16     }
17     return 0;
18 }
F

G.Barica回到顶部

题意

n个点k个方向([1,10^5]),初始在(x[1],y[1]),问按照k个方向跳完后,在哪个点,如果方向上没有点就不动,一个点跳过一次就会消失

当前在(x,y),A方向就是找一个最小的正整数P,存在一个点(x+P,y+P)

当前在(x,y),B方向就是找一个最小的正整数P,存在一个点(x+P,y-P)

当前在(x,y),C方向就是找一个最小的正整数P,存在一个点(x-P,y+P)

当前在(x,y),D方向就是找一个最小的正整数P,存在一个点(x-P,y-P)

题解

分析一下A,(x,y)->(x+P,y+P)我们做个坐标差可以得到,(y-x)=(y+P-x-P)=(y-x)那么只需要找到一个坐标差相同的并且x轴比x大的点即可

再分析一下B,(x,y)->(x+P,y-P)我们做个坐标和可以得到,(y+x)=(x+P+y-P)=(y+x)那么只需要找到一个坐标和相同的并且x轴比x大的点即可

同理C和D

先求一个坐标和,再求一个坐标差,按从小到大排序,如果相同则x小的在前面,复杂度O(nlogn)

PS:詹老哥的代码有点牛逼

UPD:下面是官方题解

Suppose we store in one linked list the points sorted by the sums of their coordinates (breaking ties by x-coordinate), and in another linked list we store the points sorted by the differences of their coordinates (again breaking ties by x-coordinate). Additionally, for each point we keep a pointer to its position in each list.

Imagine the frog is located in some point (x, y) and that the next direction to process is A. The next point in direction A is of the form (x+P, y+P) for a positive integer P. So, if it exists, the next point has the same difference of coordinates as the current point, and its x-coordinate is larger than the xcoordinate of the current point. Observe that the next point is exactly the successor of the current point in the second list. If the current point has no successor or the successor doesn't have the same difference of coordinates, the jump will not occur. If the jump occurs, delete the current point from both lists and move to the next point.

Similar reasoning can be applied to all four directions.

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N=1e5+5;
 5 
 6 struct p{
 7     int x,y;
 8 }a[N],b[N];
 9 int n,k;
10 char s[N];
11 list<p>la,lb;
12 map<pair<int,int>,list<p>::iterator>map1,map2;
13 bool cmp1(p a,p b){
14     return a.x+a.y<b.x+b.y||(a.x+a.y==b.x+b.y&&a.x<b.x);
15 }
16 bool cmp2(p a,p b){
17     return a.x-a.y<b.x-b.y||(a.x-a.y==b.x-b.y&&a.x<b.x);
18 }
19 int main(){
20     scanf("%d%d%s",&n,&k,s+1);
21     for(int i=1;i<=n;i++){
22         scanf("%d%d",&a[i].x,&a[i].y);
23         b[i]=a[i];
24     }
25     int sx=a[1].x,sy=a[1].y;
26     sort(a+1,a+1+n,cmp1);
27     sort(b+1,b+1+n,cmp2);
28     //puts("");
29     //for(int i=1;i<=n;i++)printf("a(%4d,%4d) b(%4d,%4d)\n",a[i].x,a[i].y,b[i].x,b[i].y);
30     //puts("");
31 
32     for(int i=1;i<=n;i++)la.push_back(a[i]);
33     for(int i=1;i<=n;i++)lb.push_back(b[i]);
34 
35     list<p>::iterator q;
36     
37     list<p>::iterator ita=la.begin();
38     for(;ita!=la.end();ita++)if(ita->x==sx&&ita->y==sy)break;
39     for(q=la.begin();q!=la.end();q++)map1[{q->x,q->y}]=q;
40 
41     list<p>::iterator itb=lb.begin();
42     for(;itb!=lb.end();itb++)if(itb->x==sx&&itb->y==sy)break;
43     for(q=lb.begin();q!=lb.end();q++)map2[{q->x,q->y}]=q;
44 
45     auto nowx=map1[{sx,sy}],nowy=map2[{sx,sy}];
46     for(int i=1;i<=k;i++){
47         if(s[i]=='A'){
48             q=nowy;
49             if(q==lb.end())continue;
50             q++;
51             if(q->x>=nowy->x&&q->x-q->y==nowy->x-nowy->y){
52                 la.erase(map1[{nowy->x,nowy->y}]);
53                 auto X=map1[{q->x,q->y}];
54                 nowx=X;
55                 lb.erase(nowy);
56                 nowy=q;
57             }
58         }else if(s[i]=='B'){
59             q=nowx;
60             if(q==la.end())continue;
61             q++;
62             if(q->x>=nowx->x&&q->x+q->y==nowx->x+nowx->y){
63                 lb.erase(map2[{nowx->x,nowx->y}]);
64                 auto X=map2[{q->x,q->y}];
65                 nowy=X;
66                 la.erase(nowx);
67                 nowx=q;
68             }
69         }else if(s[i]=='C'){
70             q=nowx;
71             if(q==la.begin())continue;
72             q--;
73             if(q->x<=nowx->x&&q->x+q->y==nowx->x+nowx->y){
74                 lb.erase(map2[{nowx->x,nowx->y}]);
75                 auto X=map2[{q->x,q->y}];
76                 nowy=X;
77                 la.erase(nowx);
78                 nowx=q;
79             }
80         }else if(s[i]=='D'){
81             q=nowy;
82             if(q==lb.begin())continue;
83             q--;
84             if(q->x<=nowy->x&&q->x-q->y==nowy->x-nowy->y){
85                 la.erase(map1[{nowy->x,nowy->y}]);
86                 auto X=map1[{q->x,q->y}];
87                 nowx=X;
88                 lb.erase(nowy);
89                 nowy=q;
90             }
91         }
92         //printf("a(%4d,%4d) b(%4d,%4d)\n",nowx->x,nowx->y,nowy->x,nowy->y);
93     }
94     printf("%d %d\n",nowx->x,nowx->y);
95     return 0;
96 }
G C++11 list 1121MS
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+5;
struct P {
    int sum,x,id;
    bool operator <(const P &t)const {
        if(sum!=t.sum) return sum<t.sum;
        return x<t.x;
    }
}a[N],b[N];
int x[N],y[N],f[4][N];
char s[N];
int main() {
    //freopen("in.txt","r",stdin);
    memset(f,-1,sizeof f);
    int n,k;
    scanf("%d%d%s",&n,&k,s);
    for(int i=1;i<=n;i++) {
        scanf("%d%d",&x[i],&y[i]);
        a[i]={x[i]-y[i],x[i],i},b[i]={x[i]+y[i],x[i],i};
    }
    sort(a+1,a+n+1),sort(b+1,b+n+1);
    for(int i=2;i<=n;i++) {
        if(a[i].sum==a[i-1].sum) f[0][a[i-1].id]=a[i].id,f[3][a[i].id]=a[i-1].id;
        if(b[i].sum==b[i-1].sum) f[1][b[i-1].id]=b[i].id,f[2][b[i].id]=b[i-1].id;
    }
    int pos=1;
    for(int i=0;i<k;i++) {
        int t=s[i]-'A';
        if(f[t][pos]==-1) continue;
        for(int j=0;j<4;j++) {
            if(f[j][pos]==-1) continue;
            f[3-j][f[j][pos]]=f[3-j][pos];
        }
        pos=f[t][pos];
    }
    printf("%d %d\n",x[pos],y[pos]);
    return 0;
}
G G++ 模拟list 497MS by zzl

H.Musical Themes回到顶部

题意

n([1,5000])个音符,求长度超过5的子串,需要满足,存在长度相同跟原子串不相交的新子串,使得新子串的每个数字等于对应旧子串的数字+常数P,数字范围1-88

题解

子串=新子串+P,如果对原子串进行差分,对于差分数组,子串=新子串

那么问题就变成求最长公共子串并且不相交,并且子串长度>=5

这个问题是后缀数组的经典题

求出sa和height,发现答案就在里面,所有height>=len的都可以,因为限制子串长度>=5

可以发现height是一段一段的递减,那么只需要满足每一段的max(sa)-min(sa)>=maxlen即可

maxlen我们可以二分得到,二分范围l=4,r=n/2,答案就是上面检查合法的ans再加上1,复杂度O(nlogn)

PS:sa的范围是[0,n],会多一个空串,一开始被[0,n)坑了

代码

 1 #include<bits/stdc++.h>
 2 #define cl(x) memset(x,0,sizeof(x))
 3 using namespace std;
 4 const int N=1e5+5;
 5 
 6 int n,rk[N],sa[N],height[N],tmp[N],cnt[N];int s[N];
 7 void suffixarray(int n,int m){
 8     int i,j,k;n++;
 9     for(i=0;i<n*2+5;i++)rk[i]=sa[i]=height[i]=tmp[i]=0;
10     for(i=0;i<m;i++)cnt[i]=0;
11     for(i=0;i<n;i++)cnt[rk[i]=s[i]]++;
12     for(i=1;i<m;i++)cnt[i]+=cnt[i-1];
13     for(i=0;i<n;i++)sa[--cnt[rk[i]]]=i;
14     for(k=1;k<=n;k<<=1){
15         for(i=0;i<n;i++){
16             j=sa[i]-k;
17             if(j<0)j+=n;
18             tmp[cnt[rk[j]]++]=j;
19         }
20         sa[tmp[cnt[0]=0]]=j=0;
21         for(i=1;i<n;i++){
22             if(rk[tmp[i]]!=rk[tmp[i-1]]||rk[tmp[i]+k]!=rk[tmp[i-1]+k])cnt[++j]=i;
23             sa[tmp[i]]=j;
24         }
25         memcpy(rk,sa,n*sizeof(int));
26         memcpy(sa,tmp,n*sizeof(int));
27         if(j>=n-1)break;
28     }
29     for(j=rk[height[i=k=0]=0];i<n-1;i++,k++)
30     while(~k&&s[i]!=s[sa[j-1]+k])height[j]=k--,j=rk[sa[j]+1];
31 }
32 int a[N];
33 bool check(int mid){
34     int minn=n,maxx=0;
35     for(int i=2;i<=n;i++){
36         if(height[i]>=mid)
37             minn=min(minn,min(sa[i],sa[i-1])),
38             maxx=max(maxx,max(sa[i],sa[i-1]));
39         //printf("i=%d h=%d %d %d\n",i,height[i],minn,maxx);
40         if(height[i]<mid||i==n){
41             if(minn+mid<maxx)return true;
42             minn=n,maxx=0;
43         }
44     }
45     return false;
46 }
47 int main()
48 {
49     scanf("%d",&n);
50     for(int i=0;i<n;i++)scanf("%d",&a[i]);
51     n--;
52     for(int i=0;i<n;i++)s[i]=a[i+1]-a[i]+100;
53     //for(int i=0;i<n;i++)printf("%4d ",s[i]);
54     suffixarray(n,200);
55     //puts("");
56     //多一个空串
57     //for(int i=1;i<=n;i++)printf("%4d ",i);puts("");
58     //for(int i=0;i<=n;i++)printf("%4d ",rk[i]);puts("");
59     //for(int i=0;i<=n;i++)printf("%4d ",sa[i]);puts("");
60     //for(int i=1;i<=n;i++)printf("%4d ",height[i]);puts("");
61     int l=4,r=n/2,ans=-1;
62     while(l<=r){
63         int mid=(l+r)>>1;
64         //printf("l=%d mid=%d r=%d\n",l,mid,r);
65         if(check(mid))l=mid+1,ans=mid;
66         else r=mid-1;
67     }
68     if(ans<4)printf("0");
69     else printf("%d",ans+1);
70     return 0;
71 }
72 /*
73 10
74 1 2 3 4 5 6 7 8 9 11
75 */
H

I.突破包围回到顶部

题意

n*m([2,100])的图,*代表草丛,草丛数量不超过100,#代表墙,需要从y->d,但是敌人每隔a[k]秒会切回监控,yzq就需要躲在草丛里来躲避监控,问能否从y->d

题解

因为最多只有100个草丛+起点+终点,一共102个点,可以求出两两之间的最小距离

知道时间a[k],从起点出发,遍历其余101个点,如果距离<=a[k],那么标记这个点可以到,以此类推,复杂度O(n*m*102)

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N=105;
 5 int leafx[N],leafy[N];
 6 char G[N][N];
 7 bool ok[N],changeok[N];
 8 int v[N][N][N];
 9 int dx[]={0,0,1,-1};
10 int dy[]={1,-1,0,0};
11 int sx,sy,ex,ey,n,m;
12 void bfs(int leaf,int beginx,int beginy){
13     queue<int>qx,qy;
14     qx.push(beginx);qy.push(beginy);
15     v[leaf][beginx][beginy]=0;
16     while(!qx.empty()){
17         int ux=qx.front(),uy=qy.front();
18         qx.pop();qy.pop();
19         for(int i=0;i<4;i++){
20             int vx=ux+dx[i],vy=uy+dy[i];
21             if(vx>=1&&vx<=n&&vy>=1&&vy<=m&&G[vx][vy]=='.'&&v[leaf][vx][vy]>v[leaf][ux][uy]+1){
22                 v[leaf][vx][vy]=v[leaf][ux][uy]+1;
23                 qx.push(vx);qy.push(vy);
24             }
25         }
26     }
27 }
28 int main(){
29     int t;
30     scanf("%d",&t);
31     while(t--){
32         int cnt=0;
33         scanf("%d%d",&n,&m);
34         for(int i=1;i<=n;i++)scanf("%s",G[i]+1);
35         for(int i=1;i<=n;i++)
36             for(int j=1;j<=m;j++){
37                 if(G[i][j]=='y')sx=i,sy=j,G[i][j]='.';
38                 else if(G[i][j]=='d')ex=i,ey=j,G[i][j]='.';
39                 else if(G[i][j]=='*')leafx[cnt]=i,leafy[cnt++]=j,G[i][j]='.';
40             }
41         memset(v,0x3f,sizeof v);
42         for(int i=0;i<cnt;i++)
43             bfs(i,leafx[i],leafy[i]);
44         bfs(cnt,sx,sy);leafx[cnt]=sx;leafy[cnt]=sy;cnt++;//begin
45         bfs(cnt,ex,ey);leafx[cnt]=ex;leafy[cnt]=ey;cnt++;//end
46         int k,ti;
47         scanf("%d",&k);
48         memset(ok,false,sizeof ok);
49         ok[cnt-2]=1;//begin
50         for(int i=1;i<=k;i++){
51             scanf("%d",&ti);
52             if(ok[cnt-1])continue;
53             for(int j=0;j<cnt;j++)changeok[j]=ok[j];
54             for(int j=0;j<cnt;j++){
55                 if(!ok[j])continue;
56                 for(int l=0;l<cnt;l++){
57                     if(ok[l])continue;
58                     if(v[j][leafx[l]][leafy[l]]<=ti){
59                         //printf("(%d,%d) dis=%d ti=%d i=%d\n",j,l,v[j][leafx[l]][leafy[l]],ti,i);
60                         changeok[l]=true;
61                     }
62                 }
63             }
64             for(int j=0;j<cnt;j++)ok[j]=changeok[j];
65         }
66         printf("%s\n",ok[cnt-1]?"good luck!":"poor yzq!");
67     }
68     return 0;
69 }
I

J.Trojke回到顶部

题意

n*n([1,100])的图,上面有最多26个不同的大写字母,问三点共线的数量

题解

暴力枚举,复杂度O(26^3)

PS:题意有点误导

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int x[27],y[27],tot;
 5 char G[105][105];
 6 int main(){
 7     int n;
 8     scanf("%d",&n);
 9     for(int i=1;i<=n;i++)scanf("%s",G[i]+1);
10     for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(G[i][j]!='.')x[tot]=i,y[tot++]=j;
11     int ok=0;
12     for(int i=0;i<tot;i++)
13         for(int j=i+1;j<tot;j++)
14             for(int k=j+1;k<tot;k++)
15                 if((y[j]-y[i])*(x[k]-x[i])==(x[j]-x[i])*(y[k]-y[i]))
16                     ok++;
17     printf("%d",ok);
18     return 0;
19 }
J

posted on 2020-03-14 15:41  大桃桃  阅读(484)  评论(0编辑  收藏  举报

导航