Codeforces Round #451 (Div. 2) [ D. Alarm Clock ] [ E. Squares and not squares ] [ F. Restoring the Expression ]
PROBLEM D. Alarm Clock
题
OvO http://codeforces.com/contest/898/problem/D
codeforces 898d
解
从前往后枚举,放进去后不合法就拿出来,记录拿出来的次数
中途每放进去一个数,会影响到一个区间,标记这个区间的首位(做差分,首+1,尾-1),同时维护这些标记的前缀和
#include <iostream> #include <cstring> #include <cmath> #include <algorithm> #include <cstdio> using namespace std; const int M=1e6+44; int n,m,k; int s[M]; int sum[M],num[M]; int main() { int lst,ans=0; scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++) scanf("%d",&s[i]); sort(s+1,s+n+1); memset(sum,0,sizeof(sum)); lst=0; for(int i=1;i<=n;i++) { for(int j=lst+1;j<=s[i];j++) sum[j]+=sum[j-1]; lst=s[i]; if(sum[s[i]]-sum[max(0,s[i]-m)]+1>=k) ans++; else sum[s[i]]++; } printf("%d\n",ans); return 0; }
PROBLEM E. Squares and not squares
题
OvO http://codeforces.com/contest/898/problem/E
codeforces 898e
解
预处理出10000个左右的完全平方数,然后对于每个输入的数归类他们是否是完全平方数,并且算出各自的最小代价(二分之类的)
然后根据代价排序,从小到大补足
#include <iostream> #include <cstring> #include <cmath> #include <algorithm> #include <cstdio> #include <set> using namespace std; typedef long long ll; const ll M=2e5+44; struct Node { ll num,val; } g[M],ng[M]; ll lg,lng; ll n,m; ll s[M]; ll p[M]; ll lp; set<ll> se; bool cmp(Node a,Node b) { return a.val<b.val; } void init() { se.clear(); lp=100000; for(ll i=0;i<=lp;i++) p[i]=1ll*i*i,se.insert(p[i]); } int main() { ll tmp,ans; init(); scanf("%I64d",&n); lg=lng=0; for(ll i=1;i<=n;i++) { scanf("%I64d",&s[i]); if(se.find(s[i])==se.end()) { ng[++lng].num=s[i]; tmp=upper_bound(p,p+lp+1,s[i])-p; ng[lng].val=min(p[tmp]-s[i],s[i]-p[tmp-1]); } else { g[++lg].num=s[i]; if(s[i]==0) g[lg].val=2; else g[lg].val=1; } } sort(ng+1,ng+lng+1,cmp); sort(g+1,g+lg+1,cmp); m=n/2; ans=0; if(lng>m) { for(ll i=1;i<=lng-m;i++) ans+=ng[i].val; } else { for(ll i=1;i<=lg-m;i++) ans+=g[i].val; } printf("%I64d\n",ans); return 0; }
PROBLEM F. Restoring the Expression
题
OvO http://codeforces.com/contest/898/problem/F
codeforces 898f
解
记三段为A,B,C,枚举C段的长度lc,分别判断la=lc-1,la=lc,lb=lc-1,lb=lc,这4种情况是否合法。
判断的话,做个哈希差不多的东西用来判断加法结果是否正确(哈希sed=10),截断的部分会涉及到除法,用逆元处理。哈希判断正确之后真实值再判断一次
#include <iostream> #include <cstring> #include <cmath> #include <cstdio> #include <algorithm> using namespace std; const int M=1e6+44; const int sed=10; const int mod=1e9+7; int n; char str[M]; int s[M]; int suf[M]; int bas[M],inv[M]; long long pr(int a, int b) { long long r=1,base=a; while(b!=0) { if(b&1) r=(r*base)%mod; base=(base*base)%mod; b>>=1; } return r; } bool check(int la,int lb,int lc) { int sava=la,savb=lb,savc=lc; if(la>lc || lb>lc || la<1 || lb<1 || lc<1) return false; int lia=1,lib=la+1,lic=la+lb+1; if((la>1 && s[lia]==0) || (lb>1 && s[lib]==0) || (lc>1 && s[lic]==0)) return false; int ria=la,rib=la+lb,ric=la+lb+lc; int vala,valb,valc,up=0,tmp; while(lc>0) { if(la>0) vala=s[ria]; else vala=0; if(lb>0) valb=s[rib]; else valb=0; tmp=up+vala+valb; up=tmp/10; tmp%=10; if(tmp!=s[ric]) return false; la--; lb--; lc--; ria--; rib--; ric--; } if(up) return false; for(int i=1;i<=n;i++) { printf("%d",s[i]); if(i==sava) printf("+"); if(i==sava+savb) printf("="); } return true; } int getval(int li,int ri) { int ret,tmp; tmp=(0ll+suf[li]-suf[ri+1])%mod; tmp=(1ll*tmp*inv[n-ri])%mod; ret=(tmp%mod+mod)%mod; return ret; } bool solve(int la,int lb,int lc) { int sava=la,savb=lb,savc=lc; if(la>lc || lb>lc || la<1 || lb<1 || lc<1) return false; int lia=1,lib=la+1,lic=la+lb+1; if((la>1 && s[lia]==0) || (lb>1 && s[lib]==0) || (lc>1 && s[lic]==0)) return false; int ria=la,rib=la+lb,ric=la+lb+lc; int vala,valb,valc; vala=getval(lia,ria); valb=getval(lib,rib); valc=getval(lic,ric); // cout<<la<<' '<<lb<<' '<<lc<<endl; // cout<<vala<<' '<<valb<<' '<<valc%mod<<endl; if((0ll+vala+valb)%mod==valc%mod && check(la,lb,lc)) return true; else return false; } int main() { scanf("%s",str+1); n=strlen(str+1); for(int i=1;i<=n;i++) s[i]=str[i]-'0'; bas[0]=1; for(int i=1;i<=n;i++) bas[i]=1ll*bas[i-1]*sed%mod; for(int i=0;i<=n;i++) inv[i]=pr(bas[i],mod-2); suf[n+1]=0; for(int i=n;i>=1;i--) suf[i]=(suf[i+1]+1ll*bas[n-i]*s[i]%mod)%mod; for(int i=1;i<=n;i++) { if(solve(i-1,n-i-(i-1),i) || solve(i,n-i-i,i) || solve(n-i-(i-1),i-1,i) || solve(n-i-i,i,i)) return 0; } return 0; }