1003 - Acesrc and Good Numbers
分析:首先f(n,d)可以在log的时间内算出来。
对于给定的n和d,如果f(n,d)==n,那么直接就是答案,如果f(n,d)<n,我们知道f(n,d)是单调函数,那么f(n,d)==n的数字肯定不会在f(n,d) 到 n之间出现,那么之间让n=f(n,d)就可以了,如果f(n,d)>n,我们知道,当n减少1,f(n,d)最多减少m,m是n的位数,那么n直接减掉(f(n,d)-n) / m就可以了。
#include "bits/stdc++.h"
using namespace std;
unsigned long long a[20];
unsigned long long dig[10];
unsigned long long bas[19];
unsigned long long f(unsigned long long n, int d) {
unsigned long long base = 1;
int cnt = 1;
while (base * 10 <= n) {
cnt++;
base *= 10;
}
while (base) {
int t = n / base;
dig[d] += a[cnt - 1] * t;
if (t - 1 >= d) dig[d] += bas[cnt - 1];
if (t == d) {
dig[t] += n % base;
dig[t]++;
}
n %= base;
base /= 10;
cnt--;
}
}
int main() {
bas[0] = 1;
for (int i = 1; i <= 18; ++i) {
bas[i] = bas[i - 1] * 10;
}
a[1] = 1;
for (int i = 2; i <= 18; ++i) {
a[i] = a[i - 1] * 10 + bas[i - 1];
}
int t;
cin >> t;
while (t--) {
unsigned long long x, d;
cin >> d >> x;
dig[d] = 0;
f(x, d);
while (dig[d] != x) {
if (x > dig[d])x = dig[d];
else {
int cnt = 0;
unsigned long long temp = x;
while (temp)cnt++, temp /= 10;
x -= max((unsigned long long) 1, (dig[d] - x) / cnt);
}
dig[d] = 0;
f(x, d);
}
printf("%llu\n", x);
}
}
1004 - Acesrc and Hunting
分析:当搜索到一个点时,把这个点的所有后继找出来,然后计算这些点的后继,从后继最少的点开始搜。
#include "bits/stdc++.h"
using namespace std;
int f[20][2] = {0, 2, 0, -2, 2, 0, -2, 0, 1, 1, 1, -1, -1, 1, -1, -1, 1, 2, 1, -2, -1, 2, -1, -2, 2, 1, 2, -1, -2, 1,
-2, -1, 2, 2, 2, -2, -2, 2, -2, -2};
int n, m;
bool vis[104][104];
vector<pair<int, int>> v;
struct node {
int num, x, y;
bool friend operator<(node a, node b) {
return a.num < b.num;
}
};
bool inmp(int x, int y) {
return x >= 1 && x <= n && y >= 1 && y <= m;
}
void dfs(int x, int y) {
if (v.size() == n * m)return;
int tx, ty;
vector<node> tt;
for (int i = 0; i < 20; ++i) {
tx = x + f[i][0];
ty = y + f[i][1];
if (!inmp(tx, ty))continue;
if (vis[tx][ty])continue;
int num = 0;
for (int j = 0; j < 20; ++j) {
int ttx = tx + f[j][0];
int tty = ty + f[j][1];
if (!inmp(ttx, tty))continue;
if (vis[ttx][tty])continue;
num++;
}
tt.push_back({num, tx, ty});
}
if (tt.size() == 0)return;
sort(tt.begin(), tt.end());
for (int i = 0; i < tt.size(); ++i) {
vis[tt[i].x][tt[i].y] = 1;
v.push_back(make_pair(tt[i].x, tt[i].y));
dfs(tt[i].x, tt[i].y);
if (v.size() == n * m)return;
v.erase(--v.end());
vis[tt[i].x][tt[i].y] = 0;
}
}
int main() {
int t;
cin >> t;
while (t--) {
cin >> n >> m;
v.clear();
memset(vis, 0, sizeof(vis));
vis[1][1] = 1;
v.push_back(make_pair(1, 1));
dfs(1, 1);
if (v.size() == n * m) {
puts("YES");
for (int i = 0; i < v.size(); ++i) {
printf("%d %d\n", v[i].first, v[i].second);
}
} else puts("NO");
}
}
1005 - Acesrc and String Theory
分析:首先此题与poj3693类似。
简单说一下做法,题目的要求等效于求所有子串中,是由k个循环节组成的子串的个数。那么我们枚举这个循环节的长度,设为L。显然,此时我们需要找出循环节长度为L的所有子串,假如存在一个循环次数>=2的子串,那么一定有:s[i*L] == s[(i+1)*L]的这样一组pair被包含在里面,并且长度是由他们的最长公共前缀和最长公共后缀决定,即,我们枚举s[0],s[L],s[2*L]……相邻的两个,然后求两次lcp就可以得到循环的次数。设这个子串的长度为len,那么显然,对答案的贡献应该是len - k*L + 1。
不考虑lcp的复杂度,循环次数应该是n + n/2 + n/3 + …… ≈ nlogn。
可以构造两个后缀数组来求lcp,也是比较套路的做法。构建一个正常的后缀数组,求后缀的最长公共前缀,一个将字符串反过来的后缀数组,求前缀的最长公共后缀。求p1,p2两个后缀的lcp就是height数组在rk[p1]+1到rk[p2]之间的最小值,建个ST表就可以了。
或者直接hash求lcp,由于满足单调关系,直接二分就可以了。
hash+二分代码:
#include "bits/stdc++.h"
using namespace std;
int n;
char s[300004];
unsigned long long Hash[300004];
unsigned long long base[300004];
unsigned long long geth(int l, int r) {
if (l == 0)return Hash[r];
else return Hash[r] - Hash[l - 1] * base[r - l + 1];
}
int getpre(int pos1, int pos2) {
int l = 0, r = min(pos1, pos2);
int ans = 0;
while (l <= r) {
int mid = l + r >> 1;
unsigned long long temp1 = geth(pos1 - mid, pos1);
unsigned long long temp2 = geth(pos2 - mid, pos2);
if (temp1 == temp2) {
ans = mid;
l = mid + 1;
} else r = mid - 1;
}
return ans;
}
int getlas(int pos1, int pos2) {
int l = 0, r = min(n - 1 - pos1, n - 1 - pos2);
int ans = 0;
while (l <= r) {
int mid = l + r >> 1;
unsigned long long temp1 = geth(pos1, pos1 + mid);
unsigned long long temp2 = geth(pos2, pos2 + mid);
if (temp1 == temp2) {
ans = mid;
l = mid + 1;
} else r = mid - 1;
}
return ans;
}
int main() {
int t;
cin >> t;
base[0] = 1;
for (int i = 1; i < 300004; ++i) {
base[i] = base[i - 1] * 233;
}
while (t--) {
int k;
scanf("%d", &k);
scanf("%s", s);
n = strlen(s);
if (k == 1) {
ans = 1LL * n * (n + 1) / 2;
cout << ans << endl;
continue;
}
Hash[0] = s[0] - 'a';
for (int i = 1; i < n; ++i) {
Hash[i] = Hash[i - 1] * 233 + s[i] - 'a';
}
long long ans = 0;
for (int L = 1; L <= n / k; ++L) {
int l = 0, r = L;
while (r < n) {
if (s[l] == s[r]) {
int lenl = getpre(l, r), lenr = getlas(l, r);
int len = lenl + lenr + L + 1;
if (len >= k * L) {
ans += len - k * L + 1;
}
lenr += r;
while (l <= lenr)
l += L, r += L;
} else l += L, r += L;
}
}
cout << ans << endl;
}
}
后缀数组+rmq代码:
#include "bits/stdc++.h"
using namespace std;
struct hasaki{
int n,m;
char s[300010];
int sa[300010],x[300010],y[300010],c[300010],height[300010],rk[300010];
int dp[300010][40];
void Suffix(){
for(int i=0;i<m;i++) c[i]=0;
for(int i=0;i<n;i++) c[x[i]=s[i]]++;
for(int i=0;i<m;i++) c[i]+=c[i-1];
for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
for(int k=1;k<=n;k<<=1) {
int p=0;
for(int i=n-k;i<n;i++) y[p++]=i;
for(int i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
for(int i=0;i<m;i++) c[i]=0;
for(int i=0;i<n;i++) c[x[y[i]]]++;
for(int i=0;i<m;i++) c[i]+=c[i-1];
for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1;x[sa[0]]=0;
for(int i=1;i<n;i++)
x[sa[i]]= y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;
if(p>=n) break;
m=p;
}
}
void getheight(){
for(int i=0;i<n;i++) rk[sa[i]]=i;
for(int i=0,k=0;i<n;i++){
if(rk[i]){
if(k) --k;
else k=0;
int j=sa[rk[i]-1];
while(s[i+k]==s[j+k])
k++;
height[rk[i]]=k;
}
}
}
void init(){
for (int i = 0; i < n; ++i) {
dp[i][0]=height[i];
}
for (int j = 1; (1<<j) < n; ++j) {
for (int i = 0; i + (1<<j) - 1 < n; ++i) {
dp[i][j]=0x3f3f3f3f;
dp[i][j]=min(dp[i][j-1],dp[i+(1<<j-1)][j-1]);
}
}
}
int que(int l,int r){
if(l>r)swap(l,r);
l++;
int k = log2(r-l+1);
return min(dp[l][k],dp[r-(1<<k)+1][k]);
}
int getlcp(int l,int r){
return que(rk[l],rk[r]);
}
}pre,las;
int main(){
int t;
cin>>t;
while(t--){
int k;
scanf("%d%s",&k,las.s);
int n = strlen(las.s);
for (int i = 0; i < n; ++i) {
pre.s[i] = las.s[n-1-i];
}
if(k == 1)
{
printf("%lld\n",1LL * n * (n + 1) / 2);
continue;
}
pre.s[n] = las.s[n] = 0;
pre.n = las.n = n + 1;
pre.m = las.m = 128;
pre.Suffix();
las.Suffix();
pre.getheight();
las.getheight();
pre.init();
las.init();
long long ans = 0;
for (int L = 1; L <= n/k; ++L) {
int l = 0,r = L;
while (r < n){
if(las.s[l] == las.s[r]){
int lenl = pre.getlcp(n-1-l,n-1-r);
int lenr = las.getlcp(l,r);
int len = lenl + lenr + L - 1;
if(len >= k*L){
ans += len - k*L + 1;
}
lenr += r;
while(l<=lenr){
l += L, r +=L;
}
}
else l += L,r += L;
}
}
cout<<ans<<endl;
}
}
1006 - Acesrc and Travel
分析:首先随便找一个根,然后就很容易找出,以这个根为起点,每个节点向下的先后和后手(相当于给节点加权后的最大值和最小值)的最优和次优解。然后在根据最优解和次优解找出每个节点向上的最优解,最后遍历一遍节点就可以得到答案了。
大概就是这么个套路,注意一下细节就可以过了。
#include "bits/stdc++.h"
using namespace std;
long long a[100004], b[100004];
vector<long long> v[100004];
pair<long long, long long> dpnxt[100004][2];//1min 0max
long long dppre[100004][2];
long long dfs1(long long u, long long pre, long long now) {
if (v[u].size() == 1 && pre != -1) {
dpnxt[u][now] = make_pair(0, 1e18);
return a[u] - b[u];
}
long long res = -1e18;
if (now)res = 1e18;
vector<long long> tt;
for (int i = 0; i < v[u].size(); ++i) {
if (v[u][i] == pre)continue;
if (now) {
long long temp = dfs1(v[u][i], u, now ^ 1);
if (tt.size() < 2)tt.push_back(temp);
else {
tt.push_back(temp);
sort(tt.begin(), tt.end());
tt.erase(--tt.end());
}
res = min(temp, res);
} else {
long long temp = dfs1(v[u][i], u, now ^ 1);
if (tt.size() < 2)tt.push_back(temp);
else {
tt.push_back(temp);
sort(tt.begin(), tt.end());
tt.erase(tt.begin());
}
res = max(temp, res);
}
}
if (tt.size() == 2)
dpnxt[u][now] = make_pair(tt[0], tt[1]);
else
dpnxt[u][now] = make_pair(tt[0], 1e18);
return res + a[u] - b[u];
}
long long txdy;
void dfs2(int u, int pre) {
if (pre != -1) {
vector<long long> tt;
tt.push_back(dpnxt[pre][1].first);
tt.push_back(dpnxt[pre][1].second);
sort(tt.begin(), tt.end());
for (int i = 0; i < tt.size(); ++i) {
if (tt[i] == 1e18 || tt[i] == -1e18) {
tt.erase(tt.begin() + i);
i--;
}
}
if (tt.size() == 1) {
long long tmaxi = -1e18;
if (dpnxt[u][0].first != 1e18 && dpnxt[u][0].first != -1e18)tmaxi = max(tmaxi, dpnxt[u][0].first);
if (dpnxt[u][0].second != 1e18 && dpnxt[u][0].second != -1e18)tmaxi = max(tmaxi, dpnxt[u][0].second);
if (tmaxi + a[u] - b[u] != tt[0])
dppre[u][0] = min(tt[0] + a[pre] - b[pre], dppre[pre][1] + a[pre] - b[pre]);
else
dppre[u][0] = a[pre] - b[pre] + ((dppre[pre][1] == 1e18 || dppre[pre][1] == -1e18) ? 0 : dppre[pre][1]);
} else {
long long tmaxi = -1e18;
if (dpnxt[u][0].first != 1e18 && dpnxt[u][0].first != -1e18)tmaxi = max(tmaxi, dpnxt[u][0].first);
if (dpnxt[u][0].second != 1e18 && dpnxt[u][0].second != -1e18)tmaxi = max(tmaxi, dpnxt[u][0].second);
if (tmaxi + a[u] - b[u] == tt[0])
dppre[u][0] = min(tt[1] + a[pre] - b[pre], dppre[pre][1] + a[pre] - b[pre]);
else dppre[u][0] = min(tt[0] + a[pre] - b[pre], dppre[pre][1] + a[pre] - b[pre]);
}
tt.clear();
tt.push_back(dpnxt[pre][0].first);
tt.push_back(dpnxt[pre][0].second);
sort(tt.begin(), tt.end());
for (int i = 0; i < tt.size(); ++i) {
if (tt[i] == 1e18 || tt[i] == -1e18) {
tt.erase(tt.begin() + i);
i--;
}
}
if (tt.size() == 1) {
long long tmini = 1e18;
if (dpnxt[u][1].first != 1e18 && dpnxt[u][1].first != -1e18)tmini = min(tmini, dpnxt[u][1].first);
if (dpnxt[u][1].second != 1e18 && dpnxt[u][1].second != -1e18)tmini = min(tmini, dpnxt[u][1].second);
if (tmini + a[u] - b[u] != tt[0])
dppre[u][1] = max(tt[0] + a[pre] - b[pre], dppre[pre][0] + a[pre] - b[pre]);
else
dppre[u][1] = a[pre] - b[pre] + ((dppre[pre][0] == 1e18 || dppre[pre][0] == -1e18) ? 0 : dppre[pre][0]);
} else {
long long tmini = 1e18;
if (dpnxt[u][1].first != 1e18 && dpnxt[u][1].first != -1e18)tmini = min(tmini, dpnxt[u][1].first);
if (dpnxt[u][1].second != 1e18 && dpnxt[u][1].second != -1e18)tmini = min(tmini, dpnxt[u][1].second);
if (tmini + a[u] - b[u] == tt[1])
dppre[u][1] = max(tt[0] + a[pre] - b[pre], dppre[pre][0] + a[pre] - b[pre]);
else dppre[u][1] = max(tt[1] + a[pre] - b[pre], dppre[pre][0] + a[pre] - b[pre]);
}
}
for (int i = 0; i < v[u].size(); ++i) {
if (v[u][i] == pre)continue;
dfs2(v[u][i], u);
}
}
int main() {
int t;
cin >> t;
while (t--) {
long long n;
scanf("%lld", &n);
txdy = -1e18;
for (int i = 1; i <= n; ++i) {
scanf("%lld", &a[i]);
dppre[i][1] = 1e18;
dppre[i][0] = -1e18;
v[i].clear();
}
for (int i = 1; i <= n; ++i) {
scanf("%lld", &b[i]);
}
int x, y;
for (int i = 0; i < n - 1; ++i) {
scanf("%d%d", &x, &y);
v[x].push_back(y);
v[y].push_back(x);
}
dfs1(1, -1, 0);
dfs1(1, -1, 1);
dfs2(1, -1);
for (int i = 1; i <= n; ++i) {
vector<long long> tt;
if (v[i].size() > 1 || i == 1) {
tt.push_back(dpnxt[i][1].second);
tt.push_back(dpnxt[i][1].first);
}
tt.push_back(dppre[i][1]);
sort(tt.begin(), tt.end());
for (int j = 0; j < tt.size(); ++j) {
if (tt[j] == 1e18 || tt[j] == -1e18)continue;
txdy = max(txdy, tt[j] + a[i] - b[i]);
break;
}
}
printf("%lld\n", txdy);
}
}
1009 - Calabash and Landlord
分析:枚举情况,然后暴力判断(智障做法。
其实可以直接离散化后每个点块跑dfs,就可以求出有几个联通块,就是答案。。。
这里就贴一个智障代码口八。。
#include "bits/stdc++.h"
using namespace std;
bool bhd(int x1, int y1, int x2, int y2, int px, int py){
return px > x1 && py > y1 && px < x2 && py < y2;
}
bool bhd1(int x1, int y1, int x2, int y2, int px, int py){
return px >= x1 && py >= y1 && px <= x2 && py <= y2;
}
bool x_2(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4){
return x1 == x3 && y1 == y3 && x2 == x4 && y2 == y4;
}
bool x_3(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4){
bool flag = 0;
flag |= (!bhd(x1, y1, x2, y2, x3, y3)
&& !bhd(x1, y1, x2, y2, x4, y4)
&& !bhd(x1, y1, x2, y2, x3, y4)
&& !bhd(x1, y1, x2, y2, x4, y3) );
return flag;
}
bool x_31(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4){
return bhd1(x1, y1, x2, y2, x3, y3) && bhd1(x1, y1, x2, y2, x4, y4);
}
bool x_4(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4){
bool flag = false;
flag |= (x1 == x3 && y1 == y3 && y2 < y4 && x2 > x4);
flag |= (x1 < x3 && y1 == y3 && x2 == x4 && y2 < y4);
flag |= (x1 == x3 && y1 > y3 && x2 > x4 && y2 == y4);
flag |= (x1 < x3 && y1 > y3 && x2 == x4 && y2 == y4);
flag |= (x1 < x3 && y1 == y3 && x2 > x3 && y2 == y4 && x2 < x4);
flag |= (x1 == x3 && x2 == x4 && y1 < y4 && y1 > y3 && y2 > y4);
flag |= (x1 > x3 && x2 < x4 && y1 == y3 && y2 == y4);
flag |= (x1 == x3 && x2 == x4 && y1 > y3 && y2 < y4);
return flag;
}
bool x_5(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4){
bool flag = false;
flag |= (x1 < x3 && x2 > x4 && y1 == y3 && y2 < y4);
flag |= (x1 == x3 && x2 < x4 && y1 < y3 && y2 > y4);
flag |= (x1 < x3 && x2 > x4 && y1 > y3 && y2 == y4);
flag |= (x1 > x3 && x2 == x4 && y1 < y3 && y2 > y4);
return flag;
}
bool x_6(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4){
return x1 < x3 && x2 > x4 && y1 > y3 && y2 < y4;
};
int main(){
int T; cin >> T;
while( T --) {
int x1, x2, x3, x4, y1, y2, y3, y4;
cin >> x1 >> y1 >> x2 >> y2;
cin >> x3 >> y3 >> x4 >> y4;
int ans = 4;
if(x_2(x1, y1, x2, y2, x3, y3, x4, y4)) ans = 2;
else if(x_6(x1, y1, x2, y2, x3, y3, x4, y4) || x_6(x3, y3, x4, y4, x1, y1, x2, y2)) ans = 6;
else if(x_5(x1, y1, x2, y2, x3, y3, x4, y4) || x_5(x3, y3, x4, y4, x1, y1, x2, y2)) ans = 5;
else if(x_4(x1, y1, x2, y2, x3, y3, x4, y4) || x_4(x3, y3, x4, y4, x1, y1, x2, y2)) ans = 4;
else if(x_3(x1, y1, x2, y2, x3, y3, x4, y4) && x_3(x3, y3, x4, y4, x1, y1, x2, y2)) ans = 3;
else if(x_31(x1, y1, x2, y2, x3, y3, x4, y4) || x_31(x3, y3, x4, y4, x1, y1, x2, y2)) ans = 3;
printf("%d\n", ans);
}
return 0;
}
1010 - Quailty and CCPC
分析:sort一下就可以了。
#include "bits/stdc++.h"
using namespace std;
struct node{
int name;
int num,time;
bool friend operator < (node a,node b){
if(a.num == b.num)return a.time < b.time;
return a.num > b.num;
}
}a[100004];
char s[100005][20];
int main(){
int t;
cin>>t;
while(t--){
int n,p,num,time;
cin>>n>>p;
for (int i = 0; i < n; ++i) {
scanf("%s",s[i]);
scanf("%d%d",&num,&time);
a[i] = {i,num,time};
}
int temp = n*p;
if(temp % 10 != 5)puts("Quailty is very great");
else {
sort(a,a+n);
int x = n*p/10;
printf("%s\n",s[a[x].name]);
}
}
}
1011 - Roundgod and Milk Tea
分析:依次给每个班级的学生喝奶。
优先喝班级内的学生还没有喝的班级的奶茶,不够了再喝班级内的学生已经喝过的班级的奶茶。
#include "bits/stdc++.h"
namespace fastIO {
#define BUF_SIZE 100000
bool IOerror = 0;
inline char nc() {
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if (p1 == pend) {
p1 = buf;
pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if (pend == p1) {
IOerror = 1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; }
inline void read(int &x) {
char ch;
while (blank(ch = nc()));
if (IOerror) return;
//bool flag = 0;
//if (ch == '-') {ch = nc();flag = 1; }
for (x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
//if (flag)x = -x;
}
inline void Out(int a) {
if (a < 0) {
putchar('-');
a = -a;
}
if (a >= 10) {
Out(a / 10);
}
putchar(a % 10 + '0');
}
#undef BUF_SIZE
};
using namespace fastIO;
using namespace std;
#define LL long long
const int mod = 1e9 + 7;
long long qk(long long a, long long n) {
long long res = 1;
while (n) {
if (n & 1)res = res * a % mod;
n >>= 1;
a = a * a % mod;
}
return res;
}
const int maxn = 1e6 + 5;
int a[maxn], b[maxn];
struct dd {
int id, x;
bool friend operator<(dd a, dd b) {
return a.x < b.x;
}
};
int main() {
int t;
read(t);
while (t--) {
int n;
read(n);
priority_queue<dd> q1;
long long q2 = 0;
for (int i = 0; i < n; i++) {
read(a[i]);read(b[i]);
q1.push({i, b[i]});
}
long long ans = 0;
for (int i = 0; i < n; i++) {
while (q1.size() && a[i]) {
dd now = q1.top();
q1.pop();
if (now.id <= i)continue;
else {
if (now.x > a[i]) {
now.x -= a[i];
b[now.id] = now.x;
q1.push(now);
ans += a[i];
a[i] = 0;
} else {
a[i] -= now.x;
ans += now.x;
b[now.id] = 0;
}
}
}
if (q2 >= a[i]) {
q2 -= a[i];
ans += a[i];
a[i] = 0;
} else {
ans += q2;
q2 = 0;
a[i] -= q2;
}
q2 += b[i];
}
printf("%lld\n", ans);
}
return 0;
}