2020.6.24
连着三天熬夜和一连串要处理的事情已然让我的身体有点吃不消。我只是喜欢想题的那种冥想思路开阔的感觉,但是熬夜还是不能行的。端午节前就暂时不碰竞赛了,昨天晚上算是打完了最后一场比赛。今天补完d就去打打pubg放松一下。
昨天自闭了一天之后晚上紧接着又是开幕雷击。本来以为是22:35的比赛因为我记错时间晚了10min才到。上一秒还在津津有味地看着洛谷日报。qq叮叮叮地响了起来,我一看,朋友问我a会么,我这时候才意识到,完犊子,这都开始了我竟然不知道。吃了一惊的我显然并没有被这一番事情把原本地节奏打乱,而是不慌不忙地下楼拿我买的coco蜜桃红茶冻,不得不说真的蛮好喝的 。
好了,言归正传,看题。首先我打开cf的时候已经5k人过了A,我自闭了,这还怎么翻盘啊?
仔细看了看A,题意是问一个正n边形在xOy平面内能不能在旋转的时候保证有边分别平行于x和y。从大一之后我好久没碰几何数学了,还有点怀念高中手撕双曲线,椭圆这些图形的时候,现在有点陌生了哎,前几天老师还喊我去给高中学弟学妹辅导数学,我。。。。。咳咳,怀什么久,好好看题。好吧,这道题非常显然了,看的时候就想到那就转化为4条平行于坐标轴的边,旁边再塞其他边呗,不难发现塞进去多加的边上下都必须保持一致来维护原状态,那就。。。mod 4看能不能除掉就行了。然后我眼疾手快地把4写成了2wa了一发hhhh。不过好在改了之后过了,但这特么都排到1w名了这还怎么翻盘??
代码:
#include
using namespace std;
#define limit (400 + 5)//防止溢出
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f
#define lowbit(i) i&(-i)//一步两步
#define EPS 1e-6
#define FASTIO ios::sync_with_stdio(false);cin.tie(0);
#define ff(a) printf("%d\n",a );
#define pi(a,b) pair
#define rep(i, a, b) for(int i = a; i <= b ; ++i)
#define per(i, a, b) for(int i = b ; i >= a ; --i)
#define mint(a,b,c) min(min(a,b), c)
#define MOD 988244353
#define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\data.txt", "rt", stdin)
#define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\dabiao.txt", "wt", stdout)
typedef long long ll;
typedef unsigned long long ull;
ll read(){
ll sign = 1, x = 0;char s = getchar();
while(s > '9' || s < '0' ){if(s == '-')sign = -1;s = getchar();}
while(s >= '0' && s <= '9'){x = x * 10 + s - '0';s = getchar();}
return x * sign;
}//快读
void write(ll x){
if(x < 0) putchar('-'),x = -x;
if(x / 10) write(x / 10);
putchar(x % 10 + '0');
}
int n,k;
int main() {
#ifdef LOCAL
FOPEN;
#endif
int kase;
cin>>kase;
while(kase--){
cin>>n;
if(n % 4 != 0)cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
return 0;
}
B题一般是离散数学的内容,一看果然是,看是给一个01串然后如果出现10这种就可以删掉两个其中任意一个字符,输出在若干次删除之后字典序最小的串。这题直接模拟肯定会t,肯定要有更好的算法。手动模拟了下,直接考虑分类讨论:
1)如果不存在10子串,那么就不存在删的可能,直接输出原字符串。
2)显然,开头连续的0和结尾连续的1不可能删除,无论中间间隔是什么,一定原本出现在答案中
3)中间,如果存在开头连续0和结尾连续1之外的子串,那么这些子串无论如何都可以被缩减至只剩一个0,因为要字典序最小嘛,一个1也是可以,但是不符合题意。
好了,有了这些就从两头分别扫一遍0和1,加到两个string里面去,记录下停止的下标,如果开头的0和结尾的1不接壤,那么拼接前后的时候中间就添加一个0,如果接壤就直接拼接前缀和后缀。也没那么难嘛,数组没开够re了一发,中间没考虑不加0的情况wa2了一发,然后ac,总算排名回到了6k。
代码:
#include
using namespace std;
#define limit (100000 + 5)//防止溢出
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f
#define lowbit(i) i&(-i)//一步两步
#define EPS 1e-6
#define FASTIO ios::sync_with_stdio(false);cin.tie(0);
#define ff(a) printf("%d\n",a );
#define pi(a,b) pair
#define rep(i, a, b) for(int i = a; i <= b ; ++i)
#define per(i, a, b) for(int i = b ; i >= a ; --i)
#define mint(a,b,c) min(min(a,b), c)
#define MOD 988244353
#define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\data.txt", "rt", stdin)
#define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\dabiao.txt", "wt", stdout)
typedef long long ll;
typedef unsigned long long ull;
ll read(){
ll sign = 1, x = 0;char s = getchar();
while(s > '9' || s < '0' ){if(s == '-')sign = -1;s = getchar();}
while(s >= '0' && s <= '9'){x = x * 10 + s - '0';s = getchar();}
return x * sign;
}//快读
void write(ll x){
if(x < 0) putchar('-'),x = -x;
if(x / 10) write(x / 10);
putchar(x % 10 + '0');
}
int n,k;
int a[limit],b[limit];
int main() {
#ifdef LOCAL
FOPEN;
#endif
int kase;
cin>>kase;
while(kase--){
string str;
cin>>n>>str;
string s = str;
str = ' ' + str;
int flag = 1;
string ans,pre;
rep(i ,1, n - 1){
if(str[i] == '1' && str[i + 1] == '0'){
flag = 0;
break;
}
}
if(flag){
cout<<s<<endl;
continue;
}
int fst,scd;
per(i,1,n){
if(str[i] == '0'){
scd = i;
break;
}
ans += '1';
}
rep(i ,1,n){
if(str[i] == '1'){
fst = i - 1;
break;
}
pre += '0';
}
if(fst != scd){
ans = pre + '0' + ans;
}else{
ans = pre + ans;
}
cout<<ans<<endl;
}
return 0;
}
然后开C,C题意是问有数列a和b,大小分别为n和k,a代表数字,bi代表可以从a拿的个数,b的和等于a的大小,对每个bi都有一个值,分配到的最小和最大的数字之和,问这些数字能分配之后b的值的和最大是多少。肯定不能暴力(废话)。刚看到的时候有点懵。既然说大小那排个序肯定是说的过去的,排着序就想到首先让最大值最大化,那么最大的k个值无论放在哪都是最大,先每个放一个,然后让bi - 1。还剩n-k个值,要让最小值最大化那么首先就要减少在铺垫过程中的损失,那就是从bi最小的开始放,然后统计一下答案就行了,结果又re了一发才过,我疯了,2e6明明可以用的int的结果爆炸了hhh。排名到3k了,还行,其实今天不掉分的任务已经完成了,再去看看d。
代码:
#include
using namespace std;
#define limit (1000000 + 5)//防止溢出
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f
#define lowbit(i) i&(-i)//一步两步
#define EPS 1e-6
#define FASTIO ios::sync_with_stdio(false);cin.tie(0);
#define ff(a) printf("%d\n",a );
#define pi(a,b) pair
#define rep(i, a, b) for(int i = a; i <= b ; ++i)
#define per(i, a, b) for(int i = b ; i >= a ; --i)
#define mint(a,b,c) min(min(a,b), c)
#define MOD 988244353
#define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\data.txt", "rt", stdin)
#define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\dabiao.txt", "wt", stdout)
typedef long long ll;
typedef unsigned long long ull;
ll read(){
ll sign = 1, x = 0;char s = getchar();
while(s > '9' || s < '0' ){if(s == '-')sign = -1;s = getchar();}
while(s >= '0' && s <= '9'){x = x * 10 + s - '0';s = getchar();}
return x * sign;
}//快读
void write(ll x){
if(x < 0) putchar('-'),x = -x;
if(x / 10) write(x / 10);
putchar(x % 10 + '0');
}
int n,k;
int a[limit],b[limit];
int maxx[limit],minn[limit];
int main() {
#ifdef LOCAL
FOPEN;
#endif
int kase;
cin>>kase;
while(kase--){
cin>>n>>k;
rep(i ,1,n){
cin>>a[i];
}
sort(a + 1, a + 1 + n,greater<>());
rep(i ,1,k){
cin>>b[i];
maxx[i] = -INF;
minn[i] = INF;
}
sort(b + 1, b + 1 + k);//反向sort一遍
rep(i ,1,k){
maxx[i] = minn[i] = a[i];
--b[i];//捡一个
}
int it = 0;
rep(i,1,k){
if(b[i] > 0){
minn[i] = a[k + it + b[i]];
it += b[i];
}
}
ll ans = 0;
rep(i ,1,k){
ans += (minn[i] + maxx[i]);
}
cout<<ans<<endl;
}
return 0;
}
D,1e9+7取模还多组答案一眼看出是递推或者dp预处理这样,然而11点左右打到D我脑子有些钝了不太能看得出来,查oeis也没查出来什么有用的信息。就去看E,E看了之后感觉是拓扑排序/容斥or费用流,然而这仨中拓扑排序我会一点,容斥和费用流我太菜不会啊(今天跳到一堆费用流的题应该说是疯狂暗示了,然而我直接关了),然后又去看D。手动模拟了一下发现从答案的贡献的增量应该是有一个周期为2的增长,然后中间每个增量过2个周期又开出一朵新的花。那就写写,结果最后也没有调出来,从10开始就不对了也没干交,结果今天早上看到群友的写的就发现我蠢了,旁边的树杈增量是2不是4,怪不得出锅,哎,昨天罚时吃了点亏,掉到4k了只涨了17分,如果按时好好做的话应该是2k左右,然而这能怪谁呢?re和看错时间还是自己的锅,下次注意吧。端午节前就这样,等会去吃饭,放松一下,节后备战牛客多校。
代码:
#include
using namespace std;
#define limit (3000000 + 5)//防止溢出
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f
#define lowbit(i) i&(-i)//一步两步
#define EPS 1e-6
#define FASTIO ios::sync_with_stdio(false);cin.tie(0);
#define ff(a) printf("%d\n",a );
#define pi(a,b) pair
#define rep(i, a, b) for(int i = a; i <= b ; ++i)
#define per(i, a, b) for(int i = b ; i >= a ; --i)
#define mint(a,b,c) min(min(a,b), c)
#define MOD 988244353
#define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\data.txt", "rt", stdin)
#define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\dabiao.txt", "wt", stdout)
typedef long long ll;
typedef unsigned long long ull;
ll read(){
ll sign = 1, x = 0;char s = getchar();
while(s > '9' || s < '0' ){if(s == '-')sign = -1;s = getchar();}
while(s >= '0' && s <= '9'){x = x * 10 + s - '0';s = getchar();}
return x * sign;
}//快读
void write(ll x){
if(x < 0) putchar('-'),x = -x;
if(x / 10) write(x / 10);
putchar(x % 10 + '0');
}
int n,k;
const ll mod = 1e9 + 7;
ll dp[limit],delta[limit];
int main() {
#ifdef LOCAL
FOPEN;
#endif
int kase;
cin>>kase;
dp[3] = dp[4] = 4;
delta[3] = 1;
delta[4] = 0;
rep(i ,5, 2e6){
(dp[i] = dp[i - 1] + 2 * dp[i - 2]) %= mod;
if(!delta[i - 1] && !delta[i - 2]){
(dp[i] += 4) %= mod;
delta[i] = 1;
}
}
while(kase--){
cin>>n;
if(n == 1 || n == 2){
puts("0");
continue;
}
cout<<(dp[n]%mod)<<endl;
}
return 0;
}