B - Grid with Arrows ZOJ - 4127
题意:m*n的矩阵,给一个格子都给了一个方向和步数,指向另一个格子。问能否从某个格子开始,按照给的方向和步数,走遍所有的格子。
就是求能否一笔走完所有的格子。
有向图欧拉图路径,有空再补上。
C - 0689 ZOJ - 4128
题意:给一个只由0689组成的字符串 可以把其中任意一个子串翻转180° 求总共能得到多少种不同的字符串
分析:总个数减去翻转后重复的个数。总个数:len*(len+1)/2,翻转后重复只有两头是8或者0或者一头是6另一头是9。举个例子86698,整段翻转后为86998,这个数字和86698只翻转其子串669得到的结果重复。最后注意一下只由6或者9组成的字符串无法得到它本身。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e7+10; 5 char str[maxn]; 6 int main(){ 7 int t; 8 ll z,s,e,n; 9 scanf("%d",&t); 10 while (t--){ 11 scanf("%s",str); 12 z = s = e = n = 0; 13 ll len = strlen(str); 14 for (ll i = 0; i < len; i++){ 15 if (str[i] == '0') z++; 16 else if (str[i] == '6') s++; 17 else if (str[i] == '8') e++; 18 else if (str[i] == '9') n++; 19 } 20 printf("%lld ",(len==s||len==n?0:1)+len*(len+1)/2-(z+e+z*(z-1)/2+e*(e-1)/2+s*n)); 21 } 22 return 0; 23 }
D - Pick Up ZOJ - 4129
题意:在坐标系中给出三个点A、B、C,有个人在A点有个人在B点,在A点的人要去C点,A、B点的人速度不同,A可以在一个位置和B碰面然后让B带他去C点 也可以自己去 他们能走的路必须是至少有一个轴坐标是整数 问A到C最短时间。
分析:二分时间,右端点为A到C的曼哈顿距离/A的速度。关键在于如何判断二分成立的条件。先挂个题解有空再看,其实如果数学证明出了最佳方案也没必要二分了。
题解:https://blog.csdn.net/xglync/article/details/91358127
E - Turn It Off ZOJ - 4130
题意:有一个长度为n的01串,1代表开着灯0代表关了,每次操作能把i到i+L-1这个区间的灯关闭,问k次操作内能把所有灯关闭的最小L。
分析:二分答案,判断当前答案是否成立的时候从左到右贪心。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int t,n,k; 4 string s; 5 bool check(int L){ 6 int cnt = 0; 7 for (int i = 0; i < n; i++){ 8 if (s[i] == '1'){ 9 i += L-1; 10 cnt++; 11 } 12 } 13 if (cnt <= k) return true; 14 else return false; 15 } 16 int main(){ 17 scanf("%d",&t); 18 while (t--){ 19 scanf("%d%d",&n,&k); 20 cin>>s; 21 int l = 1, r = n; 22 while (l < r){ 23 int mid = (l + r) >> 1; 24 if (check(mid)) r = mid; 25 else l = mid + 1; 26 } 27 printf("%d ",l); 28 } 29 return 0; 30 }
F - K-hour Clock ZOJ - 4131
题意:有一个K小时进制的钟,已知当前为x点,经过y时后变成z点,求任意一个满足条件的K,不满足输出-1,K<=2e9。
分析:根据(x+y)mod k = z 可以得到 x+y-z = tk (t = 1,2,3,4……)因为题目只要任意输出一个解,不妨令t = 1,也就是最小的k。如果说某个点数比这个钟的最高点数还大那这个钟是不成立的,而这个钟的k最小也就是1*k,所以如果当前的时间:x点或者经过y小时之后的时间:z点这两个时间点超过了k的话,那这个钟是不成立的。如果x+y=z则说明这个钟没有经过一个循环,也就是没有到达过0点,那这个k值理论上应该是无穷的,但k有2e9的上限所以直接输出2e9就好了。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int main(){ 5 int t; 6 ll x,y,z; 7 scanf("%d",&t); 8 while (t--){ 9 scanf("%lld%lld%lld",&x,&y,&z); 10 ll ans = x+y-z; 11 if (x >= ans || z >= ans) ans = -1; 12 if (x + y == z) ans = 2e9; 13 printf("%lld ",ans); 14 } 15 return 0; 16 }
L - Digit Product ZOJ - 4137
题意:求一段区间内的数每个位相乘的积。
分析:两个数相差超过9则必有进位也就意味着必有0出现,那全部乘起来就是0了,或者两个数的十位不相同那也肯定发生过进位,全部乘起来是0,其他的情况直接左端点枚举到右端点就好,反正枚举次数也才不超过10次。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int mod = 1e9+7; 5 int main(){ 6 int t; 7 scanf("%d",&t); 8 while (t--){ 9 ll l,r,ans = 1; 10 scanf("%lld%lld",&l,&r); 11 if (l%100/10 != r%100/10||r-l>=9) printf("0 "); 12 else{ 13 for (ll i = l; i <= r; i++){ 14 ll tmp = i; 15 while (tmp){ 16 ans *= tmp%10; 17 ans %= mod; 18 tmp /= 10; 19 } 20 } 21 printf("%lld ",ans); 22 } 23 } 24 return 0; 25 }