A.So Many Lucky Strings
坑
B.Magical Subsequence
注意到a[i]很小,所以和很小,枚举和的具体值,dp一下即可
#include<bits/stdc++.h>
#define N 500005
using namespace std;
int n,a[N],f[N],b[N],lst[N];
int main(){
scanf("%d",&n);int ans=0;
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=2;i<=200;i++){
for (int j=1;j<=200;j++) b[j]=0;
for (int j=1;j<=n;j++){
if (i-a[j]>0) lst[j]=b[i-a[j]];
b[a[j]]=j;
f[j]=0;
}
f[0]=0;
for (int j=2;j<=n;j++){
f[j]=f[j-1];
if (!lst[j]) continue;
f[j]=max(f[j],f[lst[j]-1]+1);
}
ans=max(ans,f[n]);
}
printf("%d\n",ans*2);
return 0;
}
C.Colorful Tree
坑
D.Math master
注意到位数很小,最多只有19位,因此暴力枚举分子删掉了哪些位数,判断一下分母是否可以同样做到即可
#include<bits/stdc++.h>
#define int long long
#define N 1000005
using namespace std;
const int mod=1e9+7;
const int bas=233333;
set<int>S[N];
map<int,int>mp;
int T,n,m,tot,a[N],b[N],c[N],bin[N];
signed main(){
scanf("%lld",&T);
bin[0]=1;
for (int i=1;i<=18;i++) bin[i]=bin[i-1]*10;
while (T--){
for (int i=1;i<=tot;i++) S[i].clear();
mp.clear();tot=0;
int cnt1=18,cnt2=18;
scanf("%lld%lld",&n,&m);
for (int i=0;i<=18;i++){
int tmp=n/bin[i];
if (tmp==0){cnt1=i-1;break;}
a[i]=tmp%10;
}
for (int i=0;i<=18;i++){
int tmp=m/bin[i];
if (tmp==0){cnt2=i-1;break;}
b[i]=tmp%10;
}
for (int i=1;i<(1<<(cnt1+1))-1;i++){
int now=0;
for (int j=cnt1;~j;j--)
if (!(i>>j&1)) now=now*10ll+a[j];
if (!now) continue;
for (int j=0;j<=cnt1;j++)
if (i>>j&1) c[a[j]]++;
int sum=0;
for (int j=0;j<10;j++)
sum=(sum*bas%mod+(c[j]+1))%mod;
for (int j=0;j<=cnt1;j++)
if (i>>j&1) c[a[j]]--;
if (!mp[sum]) mp[sum]=++tot;
S[mp[sum]].insert(now);
}
int ansx=n,ansy=m;
for (int i=1;i<(1<<(cnt2+1))-1;i++){
int now=0;
for (int j=cnt2;~j;j--)
if (!(i>>j&1)) now=now*10ll+b[j];
if (!now) continue;
for (int j=0;j<=cnt2;j++)
if (i>>j&1) c[b[j]]++;
int sum=0;
for (int j=0;j<10;j++)
sum=(sum*bas%mod+(c[j]+1))%mod;
for (int j=0;j<=cnt2;j++)
if (i>>j&1) c[b[j]]--;
if (!mp[sum]) continue;
__int128 tmp=(__int128)n*now;
if (tmp%m) continue;
int tmp1=tmp/m;
if (S[mp[sum]].find(tmp1)!=S[mp[sum]].end())
if (tmp1<ansx) ansx=tmp1,ansy=now;
}
printf("%lld %lld\n",ansx,ansy);
}
return 0;
}
E.Power and Modulo
找到第一个不是2^i的变值,即可算出M的值,再O(n)检验一遍即可
#include<bits/stdc++.h>
#define N 200005
using namespace std;
int n,a[N];
inline int ksm(int x,int y,int mod){
int ans1=1;while (y){
if (y&1) ans1=1ll*ans1*x%mod;
y>>=1;x=1ll*x*x%mod;
}return ans1;
}
int main(){
int T;scanf("%d",&T);
while (T--){
scanf("%d",&n);
int M=0;
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<=n;i++){
if (a[i]==(1<<(i-1))) continue;
M=(1<<(i-1))-a[i];
break;
}
if (!M){
puts("-1");
continue;
}
for (int i=1;i<=n;i++)
if (ksm(2,i-1,M)%M==a[i]) continue;
else{M=-1;break;}
printf("%d\n",M);
}
return 0;
}
F.Master Spark
坑
G.Damaged Bicycle
期望dp
发现k很小,考虑状压,正着做很难设计状态,也不好转移,考虑倒着
用dps,i表示经过了s集合的点,现在在i,到n的最小期望(此时有没有骑上车不确定)
考虑转移dps,i由dp[s∪{j}][j]转移而来,转移方程讨论j这个点是否骑到车子
即dp[s][i]=min(dp[s][i],(dp[s∪{j}][j]+1.0*dis[i][j]/t)*p[i]+(1.0*dis[i][n]/r)*(1-p[i]));
#include<bits/stdc++.h>
#define int long long
#define mk make_pair
#define N 500005
using namespace std;
long double p[N],dp[N][19];
int n,m,cnt,a[N],fa[N],dis[19][N];
vector<pair<int,int> >g[N];
priority_queue<pair<int,int> >q;
int find(int x){if(x==fa[x])return x;return fa[x]=find(fa[x]);}
inline void dij(int x){
for (int i=1;i<=n;i++) dis[x][i]=1e17;
dis[x][a[x]]=0;
q.push(mk(0,a[x]));
while (q.size()){
int u=q.top().second;
q.pop();
for (int i=0;i<(int)g[u].size();i++){
int v=g[u][i].first;
int w=g[u][i].second;
if (dis[x][v]>dis[x][u]+w){
dis[x][v]=dis[x][u]+w;
q.push(mk(-dis[x][v],v));
}
}
}
}
signed main(){
int t,r;scanf("%lld%lld",&t,&r);
scanf("%lld%lld",&n,&m);
for (int i=1;i<=n;i++) fa[i]=i;
for (int i=1;i<=m;i++){
int x,y,z;
scanf("%lld%lld%lld",&x,&y,&z);
g[x].push_back(mk(y,z));
g[y].push_back(mk(x,z));
fa[find(x)]=find(y);
}
if (find(1)!=find(n)) return puts("-1"),0;
scanf("%lld",&cnt);
for (int i=1;i<=cnt;i++) scanf("%lld%Lf",&a[i],&p[i]),p[i]=p[i]/100;
a[0]=1;
for (int i=0;i<=cnt;i++) dij(i);
for (int i=(1<<cnt)-1;i;i--){
for (int j=1;j<=cnt;j++){
if (!(i>>(j-1)&1)) continue;
dp[i][j]=1.0*dis[j][n]/t*p[j]+1.0*dis[j][n]/r*(1-p[j]);
for (int k=1;k<=cnt;k++){
if (i>>(k-1)&1) continue;
dp[i][j]=min(dp[i][j],(dp[i|(1<<(k-1))][k]+1.0*dis[j][a[k]]/t)*p[j]+(1.0*dis[j][n]/r)*(1-p[j]));
}
}
}
long double ans=1.0*dis[0][n]/t;
for (int j=1;j<=cnt;j++) ans=min(ans,1.0*dis[j][1]/t+dp[1<<(j-1)][j]);
printf("%.10Lf\n",ans);
return 0;
}
H.What logic for?
智力题
#include<bits/stdc++.h>
#define N 500005
using namespace std;
int n,m,k,t,a[N],b[N],c[N];
inline int lowbit(int x){return x&-x;}
inline void add(int x){for (int i=x;i<=t;i+=lowbit(i)) c[i]++;}
inline int sum(int x){
int ans=0;
for (int i=x;i;i-=lowbit(i)) ans+=c[i];
return ans;
}
int check(vector<int>a,vector<int>b){
multiset<int>A,B;
t=a.size();
for (int i=0;i<t;i++) A.insert(a[i]),B.insert(b[i]);
if (A!=B) return -1;
for (int i=0;i<t;i++) if (A.count(a[i])>1) return 2;
map<int,int>pos;pos.clear();
for (int i=0;i<t;i++) pos[b[i]]=i;
memset(c+1,0,t*4);
long long ans=0;
for (int i=0;i<t;i++){
a[i]=t-pos[a[i]];
ans+=sum(a[i]);
add(a[i]);
}
return ans&1;
}
int main(){
int T;scanf("%d",&T);
while (T--){
scanf("%d",&n);
for (int i=0;i<n;i++) scanf("%d",&a[i]);
scanf("%d",&m);
for (int i=0;i<m;i++) scanf("%d",&b[i]);
scanf("%d",&k);
if (n!=m){
puts("NIE");
continue;
}
int x=-1,fg=1;
for (int t=0;t<k;t++){
vector<int>a,b;
a.clear();b.clear();
for (int i=t;i<n;i+=k){
a.emplace_back(::a[i]);
b.emplace_back(::b[i]);
}
int y=check(a,b);
if (y==-1){fg=0;break;}
if (y<2){
if (x==-1) x=y;
else if (x!=y){fg=0;break;}
}
}
if (fg) puts("TAK");
else puts("NIE");
}
return 0;
}
I.Power and Zero
等价于一个长度位31的数组,每次能让一个前缀均-1,或者选中否个b[i],使得b[i]--,b[i+1]+=2
二分一个答案,等价于构造一个序列单减且均小于x,通过上述b的操作
#include<bits/stdc++.h>
#define int long long
#define N 500005
using namespace std;
int T,n,x,b[N],c[N];
inline bool check(int x){
for (int i=0;i<31;i++) c[i]=b[i];
for (int i=0;i<31;i++){
if (c[i]>x) return 0;
int tmp=(x-c[i])/2;
c[i+1]-=tmp;
x=min(x,c[i]+tmp*2);
}
return 1;
}
signed main(){
scanf("%lld",&T);
while (T--){
scanf("%lld",&n);
for (int i=0;i<31;i++) b[i]=0;
for (int i=1;i<=n;i++){
scanf("%lld",&x);
for (int j=0;j<=30;j++)
if (x>>j&1) b[j]++;
}
int l=b[0];int r=1e18;
while (l+1<r){
int mid=(l+r)>>1;
if (check(mid)) r=mid;
else l=mid;
}
if (check(l)) printf("%lld\n",l);else printf("%lld\n",r);
}
return 0;
}
J.Local Minimum
#include<bits/stdc++.h>
#define N 2005
using namespace std;
int n,m,a[N][N],b[N],c[N];
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) scanf("%d",&a[i][j]);
for (int i=1;i<=n;i++){
b[i]=a[i][1];
for (int j=2;j<=m;j++) b[i]=min(b[i],a[i][j]);
}
for (int i=1;i<=m;i++){
c[i]=a[1][i];
for (int j=2;j<=n;j++) c[i]=min(c[i],a[j][i]);
}int ans=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (a[i][j]==c[j]&&a[i][j]==b[i]) ans++;
printf("%d\n",ans);
return 0;
}
K.Wonder Egg Priority
坑
L.Karshilov's Matching Problem
坑