A-Garbage Classification
统计一下个数就可以了
#include <bits/stdc++.h>
using namespace std;
const int N = 2010;
inline int read()
{
int p=0; int f=1; char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
return p*f;
}
char a[N],b[N];
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
int t = read();
for(int T=1;T<=t;T++)
{
printf("Case #%d: ",T);
scanf("%s",a+1); int alen = strlen(a+1);
scanf("%s",b+1); int blen = strlen(b+1);
int d = 0; int w = 0; int h = 0;
for(int i=1;i<=alen;i++)
{
if(b[a[i] - 'a' + 1] == 'w') w++;
if(b[a[i] - 'a' + 1] == 'h') h++;
if(b[a[i] - 'a' + 1] == 'd') d++;
}
if(h * 4 >= alen){printf("Harmful\n"); continue;}
else if(h * 10 <= alen){printf("Recyclable\n"); continue;}
else
{
if(d >= 2*w){printf("Dry\n"); continue;}
else{printf("Wet\n"); continue;}
}
}
return 0;
}
B-Shorten IPv6 Address
字符串坑题,只需要判断一下那个0最长的在中间还是在右边,显然在中间的长度比在右边优秀
:> 0
#include <bits/stdc++.h>
using namespace std;
const int N = 2010;
inline int read()
{
int p=0; int f=1; char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
return p*f;
}
char s[N]; int a[9][5]; int len[9];
void pi(int x)
{
if(x<=9) printf("%d",x);
else printf("%c",'a' + x - 10);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
int t = read();
for(int T=1;T<=t;T++)
{
printf("Case #%d: ",T);
scanf("%s",s); memset(len,0,sizeof(len)); memset(a,0,sizeof(a));
for(int i=0;i<8;i++) for(int j=0;j<4;j++)
{
a[i][j] = ((s[i*16+j*4] - '0') << 3) + ((s[i*16+j*4+1] - '0') << 2) +
((s[i*16+j*4+2] - '0') << 1) + (s[i*16+j*4+3] - '0') ;
}
for(int i=0;i<8;i++){len[i] = 3; for(int j=0;j<4;j++) if(a[i][j] != 0){len[i] = j; break;}}
int maxlen = 0; int maxpos = -1; int j;
for(int i=0;i<8;i=j+1)
{
j = i; if(len[i] == 3 && a[i][3] == 0)
{
while(len[j] == 3 && a[j][3] == 0) j++;
if(j-i >= maxlen)
{
if(j-i == maxlen && maxpos !=0 && j==8) continue;
maxpos = i,maxlen = j-i;
}
}
}
if(maxlen < 2){maxpos = -1; maxlen = 0;}
int lst = 0;
for(int i=0;i<8;i=j)
{
if(maxpos != i)
{
for(int j=len[i];j<4;j++) pi(a[i][j]);
if(i!=7){printf(":"); lst = 1;} j = i+1;
}
else
{
if(lst == 0) printf("::"),lst = 0;
else if(lst == 1) printf(":"),lst = 0;
j = maxpos + maxlen;
}
}
printf("\n");
}
return 0;
}
C-Palindrome Mouse
题目肯定是用回文自动机搞的,然后就是把到当前点的路径上的所有点加上他们所有fail共能到达的点的个数
wcy学长说直接跳fail,拿个vector还原就好了
#include <bits/stdc++.h>
#define ll long long
#define pb push_back
#define N 100010
using namespace std;
inline ll read()
{
ll p=0; ll f=1; char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
return p*f;
}
char s[N];
struct Pam
{
ll fail[N],g[N][26],step[N],last,tot,n;
void init()
{
memset(fail,0,sizeof(fail));
memset(g,0,sizeof(g));
memset(step,0,sizeof(step));
last = n = 0; step[1] = -1; tot = fail[0] = fail[1] = 1;
}
void ins(ll nx)
{
ll p = last; n++;
while(s[n-step[p]-1] != s[n]) p = fail[p];
if(!g[p][nx])
{
ll np = ++tot; step[np] = step[p] + 2;
ll q = fail[p];
while(s[n-step[q]-1] != s[n]) q = fail[q];
fail[np] = g[q][nx]; g[p][nx] = np;
}last = g[p][nx];
}
}PAM;
vector<ll> v[N];
ll tmp = 0; ll ans = 0; bool vis[N];
void dfs(ll x)
{
v[x].clear();
ll q = x; vis[x] = 1; v[x].pb(x);
while(!vis[PAM.fail[q]]){q = PAM.fail[q]; vis[q] = 1; if(q>1) tmp++; v[x].pb(q);}
ans += tmp; if(x>1) tmp++;
for(ll i=1;i<=26;i++) if(PAM.g[x][i])
dfs(PAM.g[x][i]);
// printf("%lld :",x);
// for(ll i=0;i<v[x].size();i++) printf("%lld ",v[x][i]); printf("\n");
for(ll i=0;i<v[x].size();i++)
{
vis[v[x][i]] = 0;
if(v[x][i] > 1) tmp--;
}
}
int main()
{
ll T = read();
for(ll t=1;t<=T;t++)
{
printf("Case #%lld: ",t);
scanf("%s",s+1); ll len = strlen(s+1); PAM.init();
for(ll i=1;i<=len;i++) PAM.ins(s[i] - 'a' + 1);
// for(ll i=0;i<=PAM.tot;i++)
// {
// for(ll j=1;j<=26;j++) if(PAM.g[i][j]) printf("%d -> %d\n",i,PAM.g[i][j]);
// }
// for(ll i=1;i<=PAM.tot;i++) printf("%d ",PAM.fail[i]);
// printf("\n");
ans = tmp = 0;
dfs(0);
dfs(1);
printf("%lld\n",ans);
}
return 0;
}
D-Move
不满足二分性。。。然后只能暴力,每次其实发现性质只用把下界变成sum/k 只会有k个物品放不下,所以你暴力只要枚举到最大的容量就好了,判断的时候好像n^2比nlogn线段树快。。。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100010;
inline int read()
{
int p=0; int f=1; char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
return p*f;
}
int n,k,a[N];
multiset<int> s;
multiset<int> :: iterator it;
bool check(int x)
{
s.clear();
for(int i=1;i<=n;i++) s.insert(a[i]);
for(int i=1;i<=k;i++)
{
int lst = x;
while(1)
{
it = s.upper_bound(lst);
if(it!=s.begin()) it--;
else break ;
lst -= (*it); s.erase(it);
}
}if(s.size()) return 0;
return 1;
}
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
int t = read();
for(int T = 1;T<=t;T++)
{
n = read(); k = read(); int mx = 0; int s = 0;
for(int i=1;i<=n;i++) a[i] = read(),mx = max(mx , a[i]) ,s+=a[i];
int ret = 0;
for(int mid = max(mx,s/k);;mid++)
{
if(check(mid)){ret = mid; break;}
}printf("Case #%d: %d\n",T,ret);
}
return 0;
}
E-Androgynos
首先四个顶点的话肯定是一个Z型
考虑在这个基础上构造
一个团的自补图就变成了一个独立集
所以只要构造些团就可以了
考虑n%4=2和n%4=3是肯定不行的
就是以四个顶点来说,一个顶点一块,1块和2块连,2块和3块连,3块和4块连
然后1块和4块内部再自己连自己 所有块之间和块内部都连满就可以了
#include <bits/stdc++.h>
#define rep(i,x,y) for(int i=(x);i<=(y);i++)
#define dep(i,x,y) for(int i=(x);i>=(y);i--)
using namespace std;
const int N = 2020;
inline int read()
{
int p=0; int f=1; char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
return p*f;
}
int a[N][N];
int main()
{
// freopen("a.in","r",stdin);
int t = read();
rep(T,1,t)
{
printf("Case #%d: ",T);
int n = read();
if(n%4==2 || n%4==3){printf("No\n"); continue;}
else
{
printf("Yes\n");
rep(i,1,n) rep(j,1,n) a[i][j] = 0;
int k = n/4;
rep(i,0,k-1) rep(j,0,k-1)
{
if(i!=j) a[i*4][j*4] = a[i*4+3][j*4+3] = 1;
rep(l,0,2) a[i*4+l][j*4+l+1] = a[i*4+l+1][j*4+l] = 1;
}
if(n%4==1){rep(i,0,k-1) a[i*4][n-1] = a[n-1][i*4] = a[i*4+3][n-1] = a[n-1][i*4+3] = 1;}
rep(i,0,n-1){rep(j,0,n-1) printf("%d",a[i][j]); printf("\n");}
rep(i,0,k-1) printf("%d %d %d %d%c",i*4+2,i*4+4,i*4+1,i*4+3," \n"[(i==k-1) && (n%4==0)]);
if(n%4==1) printf("%d\n",n);
}
}
return 0;
}
G-Is Today Friday?
正解是直接跑next_permutation,去个重,然后每次都check一遍,跑到不行就停。。
然后有个玄学的蔡勒公式,套进去就可以了
#include <bits/stdc++.h>
using namespace std;
const int N = 1000010;
inline int read()
{
int p=0; int f=1; char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
return p*f;
}
string s[N];
map<string,bool>mp;
int a[N],n;
int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool fd(int y,int m,int d)
{
if(m>12 || m<1) return 0;
if((y%400==0) || ((y%100 != 0) && (y%4==0))) day[2] = 29;
else day[2] = 28;
if(day[m] < d) return 0;
if(d < 1) return 0;
if(y<1600 || y>9999) return 0;
int w=((d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7 + 7) % 7;
// printf("%d %d %d %d\n",y,m,d,w);
if(w==5) return 1;
return 0;
}
bool check()
{
for(int i=1;i<=n;i++)
{
int y = a[s[i][0]-'A'+1] * 1000 + a[s[i][1]-'A'+1] * 100 + a[s[i][2]-'A'+1] * 10 + a[s[i][3]-'A'+1];
int m = a[s[i][5]-'A'+1] * 10 + a[s[i][6]-'A'+1];
int d = a[s[i][8]-'A'+1] * 10 + a[s[i][9]-'A'+1];
if(!fd(y,m,d)) return 0;
}return 1;
}
int main()
{
int T = read();
for(int t=1;t<=T;t++)
{
printf("Case #%d: ",t);
n = read(); mp.clear(); int nn = 0;
for(int i=1;i<=n;i++)
{
string str; cin >> str;
if(mp.find(str) == mp.end()) mp[str] = 1,s[++nn] = str;
}
n = nn;
int m = 1; for(int i=1;i<=10;i++) m = m * i,a[i] = i-1;
int s = 1; bool bk = 0;
while(1)
{
// for(int i=1;i<=10;i++) printf("%d ",a[i]); printf("\n");
if(check())
{
for(int i=1;i<=10;i++) printf("%d",a[i]); printf("\n");
bk = 1; break;
}
next_permutation(a+1,a+11); s++;
if(s==m+1) break;
}
if(!bk) printf("Impossible\n");
}
return 0;
}
J-Upgrading Technology
枚举到哪个等级就好了,记得枚举0的等级,维护就瞎维护一下,维护后面的一段最小等等就行了
#include <bits/stdc++.h>
#define N 1010
#define ll long long
using namespace std;
inline ll read()
{
ll p=0; ll f=1; char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
return p*f;
}
ll c[N][N]; ll d[N]; ll sc[N][N],sd[N],ssc[N];
ll sf[N][N];
int main()
{
ll T = read();
for(ll t=1;t<=T;t++)
{
printf("Case #%lld: ",t);
ll n = read(); ll m = read(); // printf("%lld %lld\n",n,m);
memset(c,0,sizeof(c));
memset(d,0,sizeof(d));
memset(sd,0,sizeof(sd));
memset(sc,0,sizeof(sc));
memset(sf,0,sizeof(sf));
memset(ssc,0,sizeof(ssc));
for(ll i=1;i<=n;i++) for(ll j=1;j<=m;j++) c[i][j] = read();
for(ll i=1;i<=m;i++) d[i] = read(),sd[i] = sd[i-1] + d[i];
for(ll i=1;i<=n;i++)
{
sc[i][m] = 0; ll mn = 0;
for(ll j=m;j>=0;j--){
mn = mn + c[i][j];
if(mn > 0) mn = 0;
if(j) sc[i][j-1] = mn;
// printf("%lld %lld %lld\n",i,j-1,sc[i][j-1]);
}// printf("\n");
for(ll j=0;j<=m;j++) sf[i][j] = sf[i][j-1] + c[i][j];
}
// for(ll i=1;i<=m;i++) printf("%lld ",sd[i]); printf("\n");
for(ll i=0;i<=m;i++){for(ll j=1;j<=n;j++) ssc[i] += sc[j][i];}
ll ans = 0;
for(ll i=0;i<=m;i++)
{
ll s = sd[i] - ssc[i];
for(ll j=1;j<=n;j++) s-=sf[j][i];
for(ll j=1;j<=n;j++) ans = max(ans,s + sc[j][i]);
}printf("%lld\n",ans);
}
return 0;
}