bestcoder #82 div2
可能是最后的一场bestcoder,没上div1确实是有点遗憾,,,这场题目比较简单,认真打的话AK应该问题不大。
01:
判断n=x^2-y^2是否有正整数解。由于上场codeforces中毒了,这次一看01直接懵了。。。不会。。。赛后一想,,,果然水题。。。。
n=(x+y)*(x-y) , 令p=x+y,q=x-y, 则 x=(p+q)/2,y=(p-q)/2, 那么p,q必然同奇偶,从而n应该是>=3的奇数或>=6的4的倍数。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1e9+10; ll n; int main() { //freopen("in.txt","r",stdin); int T;cin>>T; while(T--){ scanf("%I64d",&n); puts(n!=1&&n!=4&&(n%4==0||n%2)?"True":"False"); } return 0; }
02:
由于中毒颇深,大脑死机了,加上环境比较吵,而且还在吃饭。。。所以。。。。
其实这题很水的。。。直接预处理出所有的数,然后二分找答案即可。。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<set> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1e9+10; ll n; set<ll> ans; void dfs(int n,int a,int b,ll num) { //cout<<"n="<<n<<" a="<<a<<" b="<<b<<" num="<<num<<endl; if(n==0){ if(num&&a==b) ans.insert(num); return; } if(a+n<b||b+n<a) return; dfs(n-1,a+1,b,num*10+4); dfs(n-1,a,b+1,num*10+7); } void Init() { ans.clear(); REP(i,1,18) dfs(i,0,0,0); } void solve() { set<ll>::iterator it=ans.lower_bound(n); if(it==ans.end()) puts("44444444447777777777"); else printf("%I64d\n",*it); } int main() { //freopen("in.txt","r",stdin); Init(); int T;cin>>T; while(T--){ scanf("%I64d",&n); solve(); } return 0; }
03:
水题。。。当时一样就看出思路了。。。。就是回文树预处理出所有长度为i的回文串的个数,然后跑背包。。。
吐槽下数据。。。我在第10分钟左右看题,第30分钟时交了第一发没过,第40分钟交了第二发,这个应该是AC的,比赛的时候给判WA了。。。导致我去改边界,再WA了几发之后终于在第59分钟过了。。。赛后才听是标程边界没处理好。。。bc就是坑。。。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=210; const int INF=1e9+10; int Nn; int c[maxn]; struct PalinTree { int ch[maxn][26],f[maxn]; int cnt[maxn],num[maxn],len[maxn]; int s[maxn]; int last,n,tot; int newnode(int l) { MS0(ch[tot]); cnt[tot]=0; num[tot]=0; len[tot]=l; return tot++; } void init() { tot=0; newnode(0); newnode(-1); last=0;n=0; s[n]=-1;f[0]=1; } int get_fail(int x) { while(s[n-len[x]-1]!=s[n]) x=f[x]; return x; } void add(int c) { c-='a'; s[++n]=c; last=get_fail(last); if(!ch[last][c]){ int cur=newnode(len[last]+2); f[cur]=ch[get_fail(f[last])][c]; ch[last][c]=cur; num[cur]=num[f[cur]]+1; } last=ch[last][c]; cnt[last]++; } void count() { for(int i=tot-1;i>=0;i--) cnt[f[i]]+=cnt[i]; } void dfs(int u) { if(u!=0&&u!=1){ c[len[u]]+=cnt[u]; } REP(i,0,25) if(ch[u][i]) dfs(ch[u][i]); } };PalinTree pt[maxn]; int dp[maxn][maxn][maxn]; int N,K,L; char s[maxn][maxn];int ls[maxn]; void solve() { MS0(dp); dp[0][0][0]=1; REP(i,1,Nn){ REP(j,0,K){ REP(k,0,L){ REP(x,0,c[i]){ if(j>=x&&k>=x*i) dp[i][j][k]|=dp[i-1][j-x][k-x*i]; } } } } puts(dp[Nn][K][L]?"True":"False"); } int main() { //freopen("in.txt","r",stdin); int T;cin>>T; while(T--){ scanf("%d%d%d",&N,&K,&L); Nn=110; MS0(c); REP(i,1,N){ scanf("%s",s[i]); ls[i]=strlen(s[i]); pt[i].init(); REP(j,0,ls[i]-1) pt[i].add(s[i][j]); pt[i].count(); pt[i].dfs(0); pt[i].dfs(1); } solve(); } return 0; }
04:
这种题已经烂大街了。。。直接对树进行一次dfs遍历,然后对dfs序列求区间第k大,,,主席树或者树套树都可以。。。然后由于n为1e5,m为1e6,所以预处理n个答案,最后o(1)回答m次询问会更好。。。卡常数卡得如此丧心病狂。。。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<vector> #include<cmath> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1e9+10; const ll MOD=1e9+7; int n,m; int val[maxn]; vector<int> G[maxn]; int u,v; double ans[maxn]; int id[maxn],fid[maxn]; int cnt[maxn]; int b[maxn],bn; struct Node { int l,r; int ls,rs; int sum; };Node tr[maxn*64]; int rt[maxn],tot; int idn; int dfs(int u) { ++idn; id[u]=idn; fid[idn]=u; int res=1; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; cnt[v]=dfs(v); res+=cnt[v]; } return res; } void push_up(int rt) { tr[rt].sum=0; if(~tr[rt].ls) tr[rt].sum+=tr[tr[rt].ls].sum; if(~tr[rt].rs) tr[rt].sum+=tr[tr[rt].rs].sum; } int build(int l,int r) { int k=++tot; tr[k]=(Node){l,r,-1,-1,0}; if(l==r) return tot; int m=(l+r)>>1; tr[k].ls=build(l,m); tr[k].rs=build(m+1,r); push_up(k); return k; } int update(int p,int c,int rt) { int k=++tot; tr[k]=tr[rt]; int l=tr[rt].l,r=tr[rt].r; if(l==r){ tr[k].sum+=c; return k; } int m=(l+r)>>1; if(p<=m) tr[k].ls=update(p,c,tr[k].ls); else tr[k].rs=update(p,c,tr[k].rs); push_up(k); return k; } int query(int k,int s,int t) { if(tr[s].l==tr[s].r) return tr[s].l; int cnt=tr[tr[s].ls].sum-tr[tr[t].ls].sum; if(k<=cnt) return query(k,tr[s].ls,tr[t].ls); else return query(k-cnt,tr[s].rs,tr[t].rs); } void Init() { tot=0; rt[0]=build(1,bn); REP(i,1,n) rt[i]=update(val[fid[i]],1,rt[i-1]); int L,R,x,y; REP(i,1,n){ L=id[i];R=id[i]+cnt[i]-1; if(cnt[i]&1){ x=query(cnt[i]/2+1,rt[R],rt[L-1]); ans[i]=1.0*b[x]; } else{ x=query(cnt[i]/2,rt[R],rt[L-1]); y=query(cnt[i]/2+1,rt[R],rt[L-1]); ans[i]=1.0*(1LL*b[x]+b[y])/2; } } } int main() { //freopen("in.txt","r",stdin); int T;cin>>T; while(T--){ scanf("%d%d",&n,&m); REP(i,1,n) G[i].clear(); REP(i,1,n) scanf("%d",&val[i]); bn=0; REP(i,1,n) b[++bn]=val[i]; sort(b+1,b+bn+1); bn=unique(b+1,b+bn+1)-(b+1); REP(i,1,n) val[i]=lower_bound(b+1,b+bn+1,val[i])-b; REP(i,1,n-1){ scanf("%d%d",&u,&v); G[u].push_back(v); } idn=0; cnt[1]=dfs(1); Init(); double res=0; REP(i,1,m){ scanf("%d",&u); res=fmod(res*10+ans[u],MOD*1.0); } printf("%.1f\n",res); } return 0; }
没有AC不了的题,只有不努力的ACMER!