Max Correct Set 有一個結論:以x+yx+yx+y為周期排列填充一定是不劣于最后的答案的 令p=x+y,r=n%pp=x+y,r=n\%pp=x+y,r=n%p ?np?\lfloor\frac{n}{p}\rfloor?pn??出現次數為ttt次,則rrr的出現次數為t+1t+1t+1,預處理一下即可
#include<cstdio>#include<cstring>#include<iostream>usingnamespace std;int n, x, y;int dp[2][1<<22], val[50];intmain(){scanf("%d %d %d",&n,&x,&y );int p = x + y, r = n % p;for(int i =0;i < p;i ++)val[i]= n / p +( i < r );int S =1<<max( x, y );memset( dp,-1,sizeof( dp ));dp[1][0]=0;for(int i =0;i < p;i ++){int now = i &1;memset( dp[now],-1,sizeof( dp[now]));for(int j =0;j < S;j ++)if(~ dp[now ^1][j]){dp[now][j <<1& S -1]=max( dp[now][j <<1& S -1], dp[now ^1][j]);if(!(1<< x -1& j )&&!(1<< y -1& j ))dp[now][j <<1& S -1|1]=max( dp[now][j <<1& S -1|1], dp[now ^1][j]+ val[i]);}}int ans =0;for(int i =0;i < S;i ++)ans =max( ans, dp[( p -1)&1][i]);printf("%d\n", ans );return0;}
二:CF1152F2
Neko Rules the Catniverse (Large Version) 簡單版: 設dpi,j,sdp_{i,j,s}dpi,j,s?:表示前iii個數,從中選了jjj個,離iii最近的mmm個元素是否選擇的狀態sss 考慮轉移到i+1i+1i+1 iii不選,直接轉移到dpi+1,j,s>>1dp_{i+1,j,s>>1}dpi+1,j,s>>1?,(舍去距離iii為mmm的元素,該元素距離i+1i+1i+1變成了m+1m+1m+1,丟掉 iii選,那么這個元素可以放在最后距離≤m\le m≤m個元素中選了的元素后面,或者放在第一個(目前iii是最大的,一定可以放在最前面
#include<cstdio>#defineintlonglong#definemod1000000007int n, k, m;int dp[100005][14][1<<4];signedmain(){scanf("%lld %lld %lld",&n,&k,&m );dp[0][0][0]=1;for(int i =0;i < n;i ++)for(int j =0;j <= k;j ++)for(int s =0;s <(1<< m );s ++){dp[i +1][j][s >>1]=( dp[i +1][j][s >>1]+ dp[i][j][s])% mod;dp[i +1][j +1][s >>1|1<< m -1]=( dp[i +1][j +1][s >>1|1<< m -1]+ dp[i][j][s]*(__builtin_popcount( s )+1)% mod )% mod;}int ans =0;for(int i =0;i <(1<< m );i ++)ans =( ans + dp[n][k][i])% mod;printf("%lld\n", ans );return0;}
#include<cstdio>#include<cstring>#defineintlonglong#definemod1000000007int n, k, m, cnt;int id[15][20];structmatrix{int c[210][210];//2^4*13=208matrix(){memset( c,0,sizeof( c ));}matrix operator*( matrix &v ){matrix ans;for(int i =1;i <= cnt;i ++)for(int j =1;j <= cnt;j ++)for(int k =1;k <= cnt;k ++)ans[i][j]=( ans[i][j]+ c[i][k]* v[k][j]% mod )% mod;return ans;}int*operator[](int x ){return c[x];}}g, f;signedmain(){scanf("%lld %lld %lld",&n,&k,&m );for(int i =0;i <= k;i ++)for(int j =0;j <(1<< m );j ++)id[i][j]=++ cnt;for(int i =0;i <= k;i ++)for(int s =0;s <(1<< m );s ++){// int t = s << 1 & ( ( 1 << m ) - 1 );// ( g[id[i][s]][id[i][t]] += 1 ) %= mod;// if( i < k ) ( g[id[i][s]][id[i + 1][t | 1] += __builtin_popcount( s ) + 1 ) %= mod;//兩種寫法均是正確的( g[id[i][s]][id[i][s >>1]]+=1)%= mod;if( i < k )( g[id[i][s]][id[i +1][s >>1|1<< m -1]]+=__builtin_popcount( s )+1)%= mod;}f[1][1]=1;while( n ){if( n &1) f = f * g;g = g * g;n >>=1;}int ret =0;for(int i =0;i <(1<< m );i ++)ret =( ret + f[1][id[k][i]])% mod;printf("%lld\n", ret );return0;}
三:CF1342F
Make It Ascending 設dpi,j,sdp_{i,j,s}dpi,j,s?:表示劃分了iii個集合,最后一個集合的合并點在jjj,最后一個集合選擇的點狀態為sss 小貪心:一個集合的合并點肯定越靠前越好,集合的和在大于上一個集合的條件下越小越好;這樣都是為了增大后面再劃分一個集合的概率 預處理集合為sss的aaa值和,然后直接轉移就沒了o(=·ω·=)m
#include<cstdio>#include<cstring>#include<iostream>usingnamespace std;#defineINF0x7f7f7f7fint T, n;int a[16], sum[1<<15], id[16];
pair <int,int> pre[16][16][1<<15];int f[16][16][1<<15];voidopt(int x ){for(int i = x;i < n;i ++) id[i]--;}voidprint(int i,int pos,int s ){if(! s )return;int lst = pre[i][pos][s].first, t = lst ^ s;for(int k =0;k < n;k ++)if( k !=( pos -1)&&(1<< k & t )){printf("%d %d\n", id[k], id[pos -1]);opt( k );}print( i -1, pre[i][pos][s].second, lst );}voidsolve(){scanf("%d",&n );for(int i =0;i < n;i ++)scanf("%d",&a[i]);int S =1<< n;for(int i =1;i < S;i ++)sum[i]= a[__builtin_ctz( i )]+ sum[i &( i -1)];for(int i =0;i <= n;i ++)for(int j =0;j <= n;j ++)memset( f[i][j],0x7f,sizeof(int)* S );f[0][0][0]=0;for(int i =0;i < n;i ++)for(int s =0;s < S;s ++)for(int j =0;j < n;j ++){if( f[i][j][s]== INF )continue;int t =( S -1)^ s;for(int k = t;k;k =( k -1)& t ){if( sum[k]<= f[i][j][s]||!( k >> j ))continue;int pos = j +__builtin_ctz( k >> j )+1;if( f[i +1][pos][s | k]> sum[k]){f[i +1][pos][s | k]= sum[k];pre[i +1][pos][s | k]=make_pair( s, j );}}}for(int i =0;i < n;i ++) id[i]= i +1;for(int i = n;i;i --)for(int j =1;j <= n;j ++)if( f[i][j][S -1]!= INF ){printf("%d\n", n - i );print( i, j, S -1);return;}}intmain(){scanf("%d",&T );while( T --)solve();return0;}創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎