总结
这场打的还可以,不算那么自闭。
开局我运气好读到签到题,极速签到,然后挂机。
郎老师发现了F的规律,凯瑞打了个A的表。
B初中数学wa太多了,罚时上天,很可惜。
赛中敲了个I,一直T,以为卡常,最后才发现复杂度假了。赛后题解看不懂,神仙DP。权当练下概率DP了,等两天如果有看得懂的题解再补。
H好像是fft板子,等点了技能点再来补,K也需要点技能点,等点完了来补。
A 题意
博弈,两堆石子,从1堆取a个,另一堆取ka个,k可以为0,a大于0.取不了判负,给出石子数,求胜负
A 思路
打表。必败态其实不多,跟n是一个数量级的。利用类似筛法的方式,筛出所有必败态就行。代码没有放完。
A 代码
#include<stack>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<deque>
#include<vector>
#include<iostream>
#include<map>
#include<set>
#include<iomanip>
using namespace std;
const int N = 5010;
bool mp[N][N];
int T,n,m;
signed main()
{
mp[2][3]=1;
mp[5][7]=1;
mp[9][12]=1;
cin>>T;
while (T--)
{
cin>>n>>m;
if (n>m) swap(n,m);
if (mp[n][m]) cout<<"Bob"<<endl;
else cout<<"Alice"<<endl;
}
return 0;
}
B 题意
给出一个等腰梯形参数,一个球,问是否从大口扔进去会卡住。
B 思路
初中数学,相似就好了,wa太多了。
这里我写出正解后居然因为没加stuck wa1,心态和代码能力还是不行,需要历练
B 代码
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<chrono>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
#define double long double
using namespace std;
typedef long long ll;
const int maxn=400505;
const int inf=0x3f3f3f3f;
int n,m,k,q;
double r,a,b,h;
void solve(){
cin>>r>>a>>b>>h;
if(b>=2*r){
cout<<"Drop"<<endl;
return ;
}
double x=b*h/(a-b);
double w=sqrt((h+x)*(h+x)+a*a/4.0);
double ans=w*2.0*r/a-x;
cout<<"Stuck"<<endl;
cout<<fixed<<setprecision(10)<<ans<<endl;
}
signed main(){
IOS
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.txt","w",stdout);
#endif
int tn=1;
while(tn--){
solve();
}
}
D 题意
01矩阵,问有多少方式把一个连续0串变成一个连续的1串,1串长度固定。
D 思路
cf a题水平,统计所有连续0串长度,给出的1串长为n的话,对max(0,len-n+1)求和就好了,len是0串长
D 代码
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<chrono>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
//#define double long double
using namespace std;
typedef long long ll;
const int maxn=2505;
const int inf=0x3f3f3f3f;
int n,m,k,q;
char a[maxn][maxn],b[maxn];
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>a[i][j];
for(int i=1;i<=n;i++)
a[i][n+1]='1';
for(int i=1;i<=m;i++) cin>>b[i];
int ans=0;
for(int i=1;i<=n;i++){
int cnt=0;
for(int j=1;j<=n+1;j++){
if(a[i][j]=='1'){
ans+=max(0,cnt-m+1);
cnt=0;
}
else{
cnt++;
}
}
}
cout<<ans<<endl;
}
signed main(){
IOS
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.txt","w",stdout);
#endif
int tn=1;
while(tn--){
solve();
}
}
F 题意
1个数3友好是说他的连续子串是3的倍数,给出lr求l到r之间3友好数个数
F 思路
lr是1e18的,所以几乎否决了除了找规律以外的一切方法。打表发现90以后所有数都是3友好的,预处理一下直接输出就行了。
F 代码
#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma G++ optimize(2)
#define endl "\n"
#define online_judge
#define debug(x) cout << "debug: " << x << endl;
using namespace std;
typedef long long ll;
const int maxn = 90;
int cnt[maxn];
signed main() {
ios::sync_with_stdio(false), cin.tie(0);
#ifndef online_judge
freopen("IO\\in.txt", "r", stdin);
freopen("IO\\out.txt", "w", stdout);
#endif
vector<int> vec{3, 6, 9, 10, 12, 13, 15, 16, 18, 19, 20, 21, 23, 24, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 42, 43, 45, 46, 48, 49, 50, 51, 53, 54, 56, 57, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 72, 73, 75, 76, 78, 79, 80, 81, 83, 84, 86, 87, 89};
for (int i = 1; i <= 89; ++i) {
int pos = upper_bound(vec.begin(), vec.end(), i) - vec.begin();
cnt[i] = pos;
}
int t;
cin >> t;
while (t--) {
ll a, b;
cin >> a >> b;
if (a > 89)
cout << b - a + 1 << endl;
else if (b <= 89)
cout << cnt[b] - cnt[a - 1] << endl;
else
cout << b - 89 + cnt[89] - cnt[a - 1] << endl;
}
return 0;
}
K 题意
给一个数组,让你重新排列,使得
∑
i
=
0
n
−
1
∣
a
i
−
b
i
∣
\sum \limits_{i=0}^{n-1} \sqrt{|a_i-b_i|}
i=0∑n−1∣ai−bi∣
最小。a为数组,b为下标(0开始)
因为n比较大(1000),不要求一定最优,差距小于一定百分比即可
s数组数据完全随机
K 思路
乱搞题。既然是较优解,可以直接类似冒泡排序一样进行操作,大概整个十几次就能过了。
K 代码
#include<cstdio>
#include<iostream>
#include<set>
#include<iomanip>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<chrono>
#include<bitset>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
//#define double long double
using namespace std;
typedef long long ll;
const int maxn=1505;
const int inf=0x3f3f3f3f;
int n,m,k;
int a[maxn];
double sq[maxn];
void solve(){
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
for(int k=1;k<=10;k++){
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++){
if(sq[abs(i-a[i])]+sq[abs(j-a[j])]>sq[abs(i-a[j])]+sq[abs(j-a[i])])
swap(a[i],a[j]);
}
}
for(int i=0;i<n;i++) cout<<a[i]<<' ';
cout<<endl;
}
signed main(){
IOS
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.txt","w",stdout);
#endif
int tn=1;
for(int i=1;i<maxn;i++)
sq[i]=sqrt(i);
cin>>tn;
while(tn--){
solve();
}
}
H 题意
n个数哈希,策略是直接模一个数。求最小的不冲突模数
范围0-50w
H 思路
冲突时当且仅当|ai-aj|%m=0
换句话说,m不能是任何一对aiaj的约数,数的范围不大,如果我们能知道所有|ai-aj|,那么我们枚举m,判断下他每一个倍数有没有出现过,就可以判断m是否可以做答案。这个复杂度是调和级数,nlogn级别的。
下面问题在于我们如何知道所有的ai-aj。这里需要一个前置知识。我们把ai看作多项式f1中x^ai
的系数,aj同样处理。那么所有ai+aj可以通过对两个多项式进行卷积得出。(显然,卷积后如果 x^k 的系数不为0,说明有两项相乘为k的情况,根据多项式的生成方式,也就是ai+aj=存在)。那么如果是ai-aj呢?不难发现可以把aj放在x^-aj的系数上。但fft不支持这种操作,那我们可以整体给他上一个偏移量d,似的所有d-aj>=0,我们卷积完之后次数全部减d就可以了。
H 代码
#include<cstdio>
#include<iostream>
#include<set>
#include<iomanip>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<chrono>
#include<bitset>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
#define int long long
//#define double long double
using namespace std;
typedef long long ll;
const int maxn=2100505;
const int inf=0x3f3f3f3f;
const int mod=998244353;
const int g=3;//原根
int n,m,k;
int a[maxn],b[maxn];
int rv[maxn];
int len,cnt;
int binpow(int a,int b=mod-2){
a%=mod;
int res = 1;
while(b>0){
if(b&1)
res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res%mod;
}
void change(){
for(int i=0;i<len;i++)
rv[i]=(rv[i>>1]>>1)|((i&1)<<(cnt-1));
}
void NTT(int *c,int type){
for(int i=0;i<len;i++)
if(i<rv[i])
swap(c[i],c[rv[i]]);
for(int mid=1;mid<len;mid<<=1){
int wn=binpow(g,(mod-1)/(mid*2));
if(type==-1) wn=binpow(wn);
for(int R=mid<<1,j=0;j<len;j+=R){
int w=1;
for(int k=0;k<mid;k++,w=(w*wn)%mod){
int x=c[j+k],y=w*c[j+mid+k]%mod;
c[j+k]=(x+y)%mod;
c[j+mid+k]=(x-y+mod)%mod;
}
}
}
if(type==-1){
int re=binpow(len);
for(int i=0;i<len;i++)
c[i]=c[i]*re%mod;
}
}
void solve(){
cin>>n;
while(n--){
int t;
cin>>t;
a[t]++;
b[500005-t]++;
}
len=1,cnt=0;
while(len<=1000000) len*=2,cnt++;
change();
NTT(a,1);NTT(b,1);
for(int i=0;i<=len;i++){
a[i]=1ll*a[i]*b[i]%mod;
}
NTT(a,-1);
bool ok=1;
for(int i=1;;i++){
ok=1;
for(int j=i;j<500005;j+=i){
if(a[j+500005]){
ok=0;
break;
}
}
if(ok){
cout<<i<<endl;
return ;
}
}
}
signed main(){
IOS
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.txt","w",stdout);
#endif
int tn=1;
//cin>>tn;
for(int __=1;__<=tn;__++){
solve();
}
}