A. Array Factory
将下标按前缀和排序,然后双指针,维护最大的右边界即可。
#include<cstdio> #include<algorithm> using namespace std; typedef long long ll; const int N=200010; int n,i,j,anslen,ansl,ansr,mr,q[N]; ll a[N],lim; inline bool cmp(int x,int y){return a[x]<a[y];} int main(){ freopen("arrayfactory.in","r",stdin); freopen("arrayfactory.out","w",stdout); scanf("%d%lld",&n,&lim); for(i=1;i<=n;i++)scanf("%lld",&a[i]),a[i]+=a[i-1]; for(i=0;i<=n;i++)q[i]=i; sort(q,q+n+1,cmp); for(i=j=0;i<=n;i++){ while(j<=n&&a[q[j]]-a[q[i]]<=lim)mr=max(mr,q[j++]); if(mr>q[i]){ int len=mr-q[i]; if(len>anslen){ anslen=len; ansl=q[i]; ansr=n-mr; }else if(len==anslen&&q[i]<ansl){ ansl=q[i]; ansr=n-mr; } } } if(!anslen)return puts("-1"),0; printf("%d %d %d",anslen,ansl,ansr); } /* a[r]-a[l]<=lim ask max r a[r]<=a[l]+lim */
B. Purchases and Bonuses
$f[i][j]$表示购买了前$i$个物品,目前有$j$积分时最多省多少钱,转移就是要么直接买,要么把积分全用完。
#include<cstdio> #include<algorithm> using namespace std; typedef long long LL; typedef pair<LL,LL>pi; const int Maxn=102,Inf=1e9; int n; int a[Maxn]; int pre[102][100020]; int pw[102][100020]; int rep[102]; int dp[2][100020]; int main(){ freopen("bonuses.in","r",stdin); freopen("bonuses.out","w",stdout); while(scanf("%d",&n)!=EOF){ for(int i=1;i<=n;i++)scanf("%d",a+i); int cs=0; for(int i=0;i<=n*1000;i++)dp[cs][i]=Inf; dp[cs][0]=0; for(int i=1;i<=n;i++,cs^=1){ for(int j=0;j<=n*1000;j++)dp[cs^1][j]=Inf; for(int j=0;j<=i*1000;j++){ if(dp[cs][j]==Inf)continue; if(dp[cs^1][j+a[i]/100]>dp[cs][j]+a[i]){ dp[cs^1][j+a[i]/100]=dp[cs][j]+a[i]; pre[i][j+a[i]/100]=j; pw[i][j+a[i]/100]=0; } int tmp=min(a[i],j); int tmpv=dp[cs][j]+a[i]-tmp; if(dp[cs^1][j-tmp]>tmpv){ dp[cs^1][j-tmp]=tmpv; pre[i][j-tmp]=j; pw[i][j-tmp]=tmp; } } } int ans=Inf,anscs; for(int i=0;i<=n*1000;i++){ if(ans>dp[cs][i]){ ans=dp[cs][i];anscs=i; } } for(int i=n;i>=1;i--){ rep[i]=pw[i][anscs]; anscs=pre[i][anscs]; } printf("%d ",ans); for(int i=1;i<=n;i++)printf("%d + %d ",a[i]-rep[i],rep[i]); } } /* a[r]-a[l]<=lim ask max r a[r]<=a[l]+lim */
C. Number of Solutions
留坑。
D. Cutting Potatoes
暴力枚举即可。
#include<cstdio> #include<algorithm> using namespace std; typedef long long LL; typedef pair<LL,LL>pi; int n,K; struct Node{ LL x,y; Node(){} Node(LL x,LL y):x(x),y(y){} bool operator <(const Node&a)const{ return x*a.y<=y*a.x; } Node operator /(const Node&a)const{ return Node(x*a.y,y*a.x); } }; int cmp(Node a,Node b){ if(a.x*b.y==a.y*b.x)return 0; return a.x*b.y>a.y*b.x?1:-1; } int a[102]; int rep[102],tmprep[102]; int main(){ freopen("cut-potatoes.in","r",stdin); freopen("cut-potatoes.out","w",stdout); while(scanf("%d%d",&n,&K)!=EOF){ for(int i=1;i<=n;i++)scanf("%d",a+i); Node ans=Node(10000000,1); for(int i=1;i<=n;i++){ for(int j=1;j<=K;j++){ Node minx=Node(a[i],j); Node maxx=Node(1,10000000); bool flag=1; for(int k=1;k<=n;k++){ int x=a[k]*minx.y/minx.x; if(!x){flag=0;break;} x=min(x,K); tmprep[k]=x; maxx=max(Node(a[k],x),maxx); } if(!flag){continue;} Node tans=maxx/minx; if(tans<ans){ ans=tans; for(int k=1;k<=n;k++)rep[k]=tmprep[k]; } } } for(int i=1;i<=n;i++)printf("%d%c",rep[i],i==n?' ':' '); } } /* a[r]-a[l]<=lim ask max r a[r]<=a[l]+lim */
E. Divide and Conquer
DP求出点数为$n$时的划分方案数,然后枚举决策找到第$k$小解即可。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef vector<int>vi; struct P{ int x,y; P(){} P(int x,int y):x(x),y(y){} bool operator<(const P&a)const{ if(x!=a.x)return x<a.x; return y<a.y; } P operator -(const P&a)const{ return P(x-a.x,y-a.y); } int operator *(const P&a)const{ return x*a.y-y*a.x; } }a[33]; int n; LL Mp[44]; int cal(P t1,P t2,P t3){ int tmp=(t2-t1)*(t3-t1); return tmp>0; } bool cmp(int x,int y){return a[x]<a[y];} LL dfs(int n){ if(Mp[n]>=0)return Mp[n]; if(!n){return Mp[n]=1;} LL t=0; for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++){ int l=j-i-1,r=n-2-l; if((l&1))continue; LL res1=dfs(l); LL res2=dfs(r); t+=res1*res2; } } return Mp[n]=t; } vector<P>rep; void pt(vi cur,LL ned){ if(cur.empty())return; bool flag=1; for(int i=0;i<cur.size()&&flag;i++){ for(int j=i+1;j<cur.size()&&flag;j++){ P t1=a[cur[i]],t2=a[cur[j]]; vi vl,vr; for(int k=0;k<cur.size();k++){ if(k==i||k==j)continue; if(cal(t1,t2,a[cur[k]]))vl.push_back(cur[k]); else vr.push_back(cur[k]); } if(vl.size()&1)continue; sort(vl.begin(),vl.end(),cmp); sort(vr.begin(),vr.end(),cmp); LL res1=Mp[vl.size()]; LL res2=Mp[vr.size()]; if(ned>=res1*res2)ned-=res1*res2; else{ rep.push_back(t1); rep.push_back(t2); pt(vl,ned/res2); pt(vr,ned%res2); flag=0; break; } } } } int main(){ freopen("dnc.in","r",stdin); freopen("dnc.out","w",stdout); //cal(P(0,0),P(2,0),P(2,1)); while(scanf("%d",&n)!=EOF){ for(int i=0;i<n;i++){ int x,y; scanf("%d%d",&x,&y); a[i]=P(x,y); } vi ori(n,0); for(int i=0;i<n;i++)ori[i]=i; sort(ori.begin(),ori.end(),cmp); memset(Mp,-1,sizeof Mp); dfs(n); // for(int i=1;i<=n;i++)printf("%lld ",Mp[i]);puts(""); rep.clear(); LL k;scanf("%lld",&k); pt(ori,k); for(int i=0;i<rep.size();i++)printf("%d %d ",rep[i].x,rep[i].y); } } /* a[r]-a[l]<=lim ask max r a[r]<=a[l]+lim */
F. Doubling
大范围直接$/2$构造,小范围DP求解。
#include<cstdio> #include<algorithm> #include<string> #include<iostream> using namespace std; typedef long long ll; const int N=200010; const int inf=100000000; typedef pair<int,string>P; int n,i,j; P f[111]; string cal(int n){ if(n<=100)return f[n].second; if(n&1)return cal(n-1)+"1"; return "["+cal(n/2)+"]"; } int main(){ freopen("doubling.in","r",stdin); freopen("doubling.out","w",stdout); scanf("%d",&n); f[0]=P(0,""); f[1]=P(1,"1"); f[2]=P(2,"11"); for(i=3;i<=100;i++){ f[i]=P(inf,""); for(j=1;j<i;j++){ P x=f[j]; x.first+=f[i-j].first; x.second+=f[i-j].second; f[i]=min(f[i],x); } if(i%2==0){ P x(f[i/2].first+2,"["+f[i/2].second+"]"); f[i]=min(f[i],x); } } cout<<cal(n)<<endl; return 0; } /* a[r]-a[l]<=lim ask max r a[r]<=a[l]+lim */
G. New Collection
随机100轮算出期望集合大小,然后找到差距最近的即可。
#include <bits/stdc++.h> using namespace std ; typedef long long LL ; typedef pair < int , int > pii ; #define getid( l , r ) l + r | ( l != r ) set < string> s ; double magic[7]={10.0,100.0,999.96,6325.61,9517.19,9950.67,9995.01}; void solve () { string c ; for ( int i = 1 ; i <= 10000 ; ++ i ) { cout << "+" << endl ; fflush ( stdout ) ; cin >> c ; s.insert(c); } int x = ( int ) s.size () ; double ret=1e9; int ans; for(int i=0;i<7;i++){ double now=fabs(1.0*x-magic[i]); if(now<ret)ret=now,ans=i; } int fin=1; for(int i=0;i<=ans;i++)fin*=10; printf("= %d ",fin); fflush ( stdout ) ; } int main () { solve () ; return 0 ; }
H. Path or Coloring
贪心染色,如果可以$k$染色,那么就好了,否则必然存在长度为$k$的简单路径。
#include<cstdio> #include<algorithm> #include<string> #include<iostream> #include<cstdlib> using namespace std; typedef long long ll; const int N=1010; const int M=20010; const int inf=100000000; int Case,n,m,K,i,j,x,y,g[N],v[M],nxt[M],ed,vis[N],col[N],pos; inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;} void dfs(int x){ pos++; for(int i=g[x];i;i=nxt[i])if(col[v[i]])vis[col[v[i]]]=pos; for(int i=1;;i++)if(vis[i]<pos){ col[x]=i; break; } for(int i=g[x];i;i=nxt[i])if(!col[v[i]])dfs(v[i]); } void solve(){ scanf("%d%d%d",&n,&m,&K); for(ed=0,i=1;i<=n;i++)g[i]=col[i]=0; while(m--)scanf("%d%d",&x,&y),add(x,y),add(y,x); for(i=1;i<=n;i++)if(!col[i])dfs(i); bool flag=0; for(i=1;i<=n;i++)if(col[i]>K){flag=1;break;} if(!flag){ printf("coloring"); for(i=1;i<=n;i++)printf(" %d",col[i]); return; } for(i=1;i<=n;i++)if(col[i]==K+1){x=i;break;} printf("path"); for(i=1;i<=K+1;i++){ printf(" %d",x); for(j=g[x];j;j=nxt[j])if(col[v[j]]==col[x]-1){ x=v[j]; break; } } } int main(){ freopen("pathorcoloring.in","r",stdin); freopen("pathorcoloring.out","w",stdout); scanf("%d",&Case); while(Case--){ solve(); puts(""); } }
I. Double Shuffle
留坑。
J. Timer
按题意模拟。
#include <bits/stdc++.h> using namespace std ; typedef long long LL ; typedef pair < int , int > pii ; #define clr( a , x ) memset ( a , x , sizeof a ) #define getid( l , r ) l + r | ( l != r ) const int MAXN = 100005 ; char s[12][65] ; char a[12][MAXN] ; char digit[10][8][9] = { { ".XXXXX..", "XX..XXX.", "XX.XXXX.", "XXXX.XX.", "XXX..XX.", "XXX..XX.", ".XXXXX..", "........", }, { "...XX...", "..XXX...", ".XXXX...", "...XX...", "...XX...", "...XX...", ".XXXXXX.", "........", }, { ".XXXXX..", "XX...XX.", ".....XX.", "...XXX..", ".XXX....", "XX......", "XXXXXXX.", "........", }, { ".XXXXX..", "XX...XX.", ".....XX.", "..XXXX..", ".....XX.", "XX...XX.", ".XXXXX..", "........", }, { "...XXX..", "..XXXX..", ".XX.XX..", "XX..XX..", "XXXXXXX.", "....XX..", "...XXXX.", "........", }, { "XXXXXXX.", "XX......", "XXXXXX..", ".....XX.", ".....XX.", "XX...XX.", ".XXXXX..", "........", }, { ".XXXXX..", "XX...XX.", "XX......", "XXXXXX..", "XX...XX.", "XX...XX.", ".XXXXX..", "........", }, { "XXXXXXX.", "XX...XX.", "X....XX.", "....XX..", "...XX...", "..XX....", "..XX....", "........", }, { ".XXXXX..", "XX...XX.", "XX...XX.", ".XXXXX..", "XX...XX.", "XX...XX.", ".XXXXX..", "........", }, { ".XXXXX..", "XX...XX.", "XX...XX.", ".XXXXXX.", ".....XX.", "XX...XX.", ".XXXXX..", "........", }, } ; void paint ( int x , int v ) { for ( int i = 3 ; i < 10 ; ++ i ) { for ( int j = x ; j < x + 8 ; ++ j ) { a[i][j] = digit[v][i - 3][j - x] ; } } } void mark ( int x ) { a[0][x + 3] = a[0][x + 4] = a[1][x + 3] = a[1][x + 4] = 'X' ; } int check ( int x ) { for ( int i = 0 ; i < 12 ; ++ i ) { for ( int j = 0 ; j < 60 ; ++ j ) { if ( s[i][j] == '-' ) continue ; if ( s[i][j] != a[i][x + j] ) return 0 ; } } return 1 ; } void solve () { for ( int i = 0 ; i < 12 ; ++ i ) { scanf ( "%s" , s[i] ) ; } int ans = 3470 ; for ( int i = 0 ; ; ++ i ) { if ( check ( i ) ) { printf ( "%02d:%02d " , ans / 60 , ans % 60 ) ; return ; } ans -= 5 ; if ( ans < 0 ) ans += 3600 ; } } void show ( int l , int r ) { for ( int i = 0 ; i < 12 ; ++ i ) { for ( int j = l ; j < r ; ++ j ) { printf ( "%c" , a[i][j] ) ; } puts ( "" ) ; } } int main () { clr ( a , '.' ) ; int x = 0 ; for ( int i = 0 ; i < 50000 ; i += 12 ) { if ( x % 5 == 0 ) { if ( x < 10 ) paint ( i , x ) ; else { paint ( i + 4 , x % 10 ) ; paint ( i - 4 , x / 10 ) ; } } mark ( i ) ; x = ( x - 1 + 60 ) % 60 ; } //show ( 0 , 110 ) ; solve () ; /* for ( int i = 0 ; i < 10 ; ++ i ) { scanf ( "%d" , &n ) ; printf ( "{ " ) ; for ( int j = 0 ; j < 8 ; ++ j ) { scanf ( "%s" , tmp ) ; printf ( ""%s", ", tmp ); } printf ( "}, " ) ; } */ return 0 ; }
K. Ultraprime Numbers
答案最多只有$9$项。
#include<cstdio> #include<algorithm> #include<string> #include<iostream> using namespace std; typedef long long ll; const int N=2010; const int inf=100000000; int n,i,j,p[N/10],tot;bool is[N],v[N]; int q[1111],ans; inline bool check(int x){ if(!is[x])return 0; static int f[100]; int n=0; while(x)f[++n]=x%10,x/=10; for(int i=n;i;i--){ int t=0; for(int j=i;j;j--){ t=t*10+f[j]; if(!is[t])return 0; } } return 1; } int main(){ freopen("ultraprime.in","r",stdin); freopen("ultraprime.out","w",stdout); //scanf("%d",&n); n=2000; for(i=2;i<=n;i++){ if(!v[i])is[i]=1,p[tot++]=i; for(j=0;j<tot;j++){ if(i*p[j]>n)break; v[i*p[j]]=1; if(i%p[j]==0)break; } } for(i=2;i<=n;i++)if(check(i)){ q[++ans]=i; // printf("%d %d ",ans,i); if(ans==1000)break; } scanf("%d",&n); if(ans<n)puts("-1");else printf("%d",q[n]); return 0; } /* a[r]-a[l]<=lim ask max r a[r]<=a[l]+lim */