CF 535C Tavas and Karafs
题目大意:给你一个无限长的等差数列,每次给一个起点L,可以吃T轮,每可以把M个数吃一口(-1),问最大的R使得区间[L,R]被吃完
思路:显然给定一个区间[L,R]后很容易贪心出能不能被吃完,并且发现该性质有单调性也就是如果[L,R]可以吃完,那[L,R-1]也可以,且存在最大的R使得[L,R+1]不满足条件,于是二分一下就可以了
1 #include<iostream> 2 #include<cstdio> 3 #define ll long long 4 using namespace std; 5 ll a,b,n,l,t,m,rr,lr; 6 int check(ll k) 7 { 8 ll f = a + (l - 1) * b,rrr = a + (k - 1) * b,su=((f+rrr)*(k-l+1))>>1; 9 if(t*m<su || rrr > t)return 0; 10 else return 1; 11 } 12 int main() 13 { 14 cin>>a>>b>>n; 15 for(int i=1;i<=n;i++) 16 { 17 cin>>l>>t>>m; 18 if(a+b*(l-1) > t) 19 { 20 puts("-1"); 21 continue; 22 } 23 lr = l; 24 rr = l + t+10; 25 while(lr<rr) 26 { 27 int mid = (lr + rr+ 1) >> 1; 28 if(check(mid))lr=mid;else rr=mid-1; 29 } 30 cout<<lr<<endl; 31 } 32 return 0; 33 }
CF 533B. Work Group
题目大意:给出一棵有根树,每个点都有点权,从中选出一些点,使得每个选中的点的子树中都有偶数个选中点,求选出点最大的点权
思路:很明显的树dp,显然选中当前点的话,那它的子数选中的点只能选择偶数,如果不选当前的点,子树可以选偶数或奇数个点,那接下来问题就转化成了对于一个点,它的子树可以选奇数个点或偶数的点,以及一个权值,如何选才能使权值最大并且点数为奇数/偶数。这个显然是一个一维的DP,于是问题得到解决
唔,细节处理还是很重要的,由于一开始什么0个点都没选的时候点数是偶数,因此需要一开始将奇数转移的地方封印起来,直到选了奇数个后才能用odd转移
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define maxn 400000 5 using namespace std; 6 long long now=0,head[maxn],next[maxn],point[maxn],p[maxn]; 7 long long dp[400000][3],root; 8 void add(int x,int y) 9 { 10 next[++now]=head[x]; 11 head[x]=now; 12 point[now]=y; 13 } 14 long long dfs(long long k,long long par) 15 { 16 if(dp[k][par]!=-1)return dp[k][par]; 17 long long even = 0 ,odd = -1; 18 for(int i=head[k];i;i=next[i]) 19 { 20 long long pp = point[i],u=dfs(pp,0) , v = dfs(pp,1); 21 long long tempe = even , tempo = odd; 22 even += u;odd += u; 23 if(v != -1) 24 { 25 if(tempo != -1)even = max(even , tempo + v); 26 odd = max(odd , tempe +v); 27 } 28 } 29 dp[k][0]=even; 30 dp[k][1] = max(even + p[k], odd); 31 return dp[k][par]; 32 } 33 int main() 34 { 35 long long n,x; 36 memset(dp,-1,sizeof(dp)); 37 cin>>n; 38 for(int i=1;i<=n;i++) 39 { 40 cin>>x>>p[i]; 41 if(x==-1)root=i; 42 else 43 { 44 add(x,i); 45 } 46 } 47 cout<<max(dfs(root,0),dfs(root,1))<<endl; 48 return 0; 49 }
GCJ 2015 A. Counter Culture
题目大意:给你一个数,从0出发每次可以对这个数进行两个操作:1.将这个数反转:也就是1234变成4321 2.将这个数加一
问从0出发最少多少次操作能变成这个数
思路:这题做的,快苦了。。。首先20一下只能一步一步加,以上呢?先凑出来到这个位数至少需要多少步,比如到达100需要多少步,1000需要多少步,然后将末尾一半的数凑成高位,反转,再将后一半的数凑成高位就能过大数据了,可惜的是闹抽两句话写反了结果fst!!!!
1 #include<iostream> 2 #include<fstream> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 500 6 using namespace std; 7 ifstream fin("a.in"); 8 ofstream fout("a.out"); 9 //#define fin cin 10 //#define fout cout 11 int deg[100]={0,1,10,29,138,337,1436,3435,14434,34433,144432,344431,1444430,3444429,14444428}; 12 int main() 13 { 14 long long t,n,cas=0; 15 fin>>t; 16 while(t--) 17 { 18 long long ans=0; 19 fin>>n; 20 int flag=0; 21 if(n<=20) 22 { 23 fout<<"Case #"<<++cas<<": "<<n<<endl; 24 } 25 else 26 { 27 long long temp=n; 28 if(n%10==0) 29 { 30 n--; 31 flag=1; 32 } 33 int a[100],h=0; 34 while(n) 35 { 36 a[++h]=n%10; 37 n/=10; 38 } 39 int u=h>>1; 40 ans += deg[h]; 41 long long v=0; 42 for(int i=h-u+1;i<=h;i++) 43 { 44 v = v * 10 + a[i]; 45 } 46 ans += v; 47 v=0; 48 for(int i=h-u;i>=1;i--) 49 { 50 v= v*10 +a[i]; 51 } 52 ans+=v; 53 v=1; 54 for(int i=1;i<h;i++)v*=10; 55 if(flag)ans++; 56 fout<<"Case #"<<++cas<<": "<<min(ans,temp-v+deg[h])<<endl; 57 } 58 } 59 return 0; 60 }
Codeforces Round #300 B. Quasi Binary
题目大意:给出一个数(0到1e6),问你它能是最少多少quasibinary的和,一个十进制数是quasibinary当且仅当它十进制数位上只有0和1
思路:显然这个范围内quasibinary不多,先预处理出来,然后就是一个裸到不行的DP,记录路径就可以
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 2000000 6 using namespace std; 7 int a[maxn],h=0,ini[maxn],dp[maxn],last[maxn],ans[maxn]; 8 void add(int temp[]) 9 { 10 int sum=0; 11 for(int i=1;i<=7;i++)sum = sum*10 + temp[i]; 12 ini[++h]=sum; 13 } 14 void dfs(int k) 15 { 16 if(k>7){add(a);return ;} 17 a[k]=1;dfs(k+1); 18 a[k]=0;dfs(k+1); 19 } 20 int dfs2(int k) 21 { 22 if(dp[k]!=-1)return dp[k]; 23 int ret=0x3f3f3f3f; 24 for(int i=1;i<=h;i++) 25 { 26 if(k-ini[i]>=0) 27 { 28 int u=dfs2(k-ini[i]); 29 if(u < ret) 30 { 31 ret = u; 32 last[k] = i; 33 } 34 } 35 else break; 36 } 37 return dp[k]=ret+1; 38 } 39 int main() 40 { 41 int n; 42 scanf("%d",&n); 43 dfs(1); 44 memset(dp,-1,sizeof(dp)); 45 dp[0]=0; 46 h--; 47 sort(ini+1,ini+1+h); 48 printf("%d\n",dfs2(n)); 49 int v=0; 50 while(last[n]!=0) 51 { 52 ans[++v]=ini[last[n]]; 53 n-=ini[last[n]]; 54 } 55 sort(ans+1,ans+1+v); 56 for(int i=1;i<=v;i++)printf("%d ",ans[i]); 57 return 0; 58 }