A
水题
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a,b,c;scanf("%d%d%d",&a,&b,&c);
if(a+b+c>=22)
cout<<"bust"<<endl;
else cout<<"win"<<endl;
}
B
水题
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
char s[N];
int main()
{
scanf("%s",s+1);
int n=strlen(s+1);
int ans=0;
int l=1,r=n;
while(l<=r)
{
if(s[l++]!=s[r--]) ans++;
}
cout<<ans<<endl;
}
C
简单状压
#include<bits/stdc++.h>
using namespace std;
const int N=16;
int n;
vector<int>v[N][2];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int x;scanf("%d",&x);
for(int j=1;j<=x;j++)
{
int y,z;scanf("%d%d",&z,&y);
v[i][y].push_back(z);
}
}
int ans=0;
for(int i=0;i<1<<n;i++)
{
bool flag=true;
for(int j=1;j<=n;j++)
{
bool f=true;
for(int k=0;k<v[j][0].size();k++)
if(1<<(v[j][0][k]-1)&i) f=false;
for(int k=0;k<v[j][1].size();k++)
if(!((1<<v[j][1][k]-1)&i)) f=false;
if(f&&(!(1<<(j-1)&i))) flag=false;
if(!f&&(1<<(j-1)&i)) flag=false;
}
if(flag) ans=max(ans,__builtin_popcount(i));
}
printf("%d\n",ans);
}
D
简单拆位
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+5,mod=1e9+7;
int n;
ll a[N],b[60];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
for(int j=0;j<60;j++)
if(a[i]>>j&1) b[j]++;
}
ll ans=0;
for(int i=1;i<=n;i++)
{
for(int j=0;j<60;j++)
if(a[i]>>j&1) b[j]--;
for(int j=0;j<60;j++)
if(a[i]>>j&1)
{
ans=(ans+(1ll<<j)%mod*(n-i-b[j])%mod)%mod;
}
else
{
ans=(ans+(1ll<<j)%mod*b[j]%mod)%mod;
}
}
printf("%lld\n",ans);
}
E
dp[i][j][k]表示走到格子i,j,sum1-sum2=k的状态是否存在。
dp一遍即可,用bitset优化方便又省时。
#include<bits/stdc++.h>
using namespace std;
const int N=85,low=81*81;
int a[N][N],b[N][N];
bitset<N*N*2>dp[N][N];
int mx[N][N];
int n,m;
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++)
for(int j=1;j<=m;j++)
scanf("%d",&b[i][j]);
dp[1][1].set(a[1][1]-b[1][1]+low,1);
dp[1][1].set(b[1][1]-a[1][1]+low,1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(i==1&&j==1) continue;
int x=abs(a[i][j]-b[i][j]);
dp[i][j]=(dp[i-1][j]<<x)|(dp[i-1][j]>>x)|(dp[i][j-1]<<x)|(dp[i][j-1]>>x);
}
int ans=1e9;
for(int i=0;i<=low*2;i++)
if(dp[n][m][i])
{
ans=min(ans,abs(i-low));
}
printf("%d\n",ans);
}
F
选定了i个x,可以决定能选多少个d,对于x和d的符号相等,设k位x和d的最小公倍数,那么加d/k个x
就要减d/x个k使得原来的值相等,那么枚举x的个数,确定选不同的d有多少方案数
然后容斥一下,假如当前有i个x,把有i+d/k个x的方案数给减去,时间复杂度O(n)。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
typedef long long ll;
ll n,x,d;
ll ans=0,f[N],sum[N];
int main()
{
scanf("%lld%lld%lld",&n,&x,&d);
if(x==0&&d==0)
{
cout<<1<<endl;return 0;
}
if(x<0&&d<0)
x*=-1,d*=-1;
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+i-1;
ll k=__gcd(x,d),xx=x/k,dd=d/k;
if(xx>=0&&dd>=0)
{
for(int i=0;i<=n;i++)
{
ll l=sum[i],r=sum[n]-sum[n-i];
if(l>r) swap(l,r);
ans+=r-l+1;
if(i+dd<=n)
{
l=max(l,sum[i+dd]+xx);
ans-=max(0ll,r-l+1);
}
}
}
else
{
if(xx<0) xx*=-1;
if(dd<0) dd*=-1;
for(int i=0;i<=n;i++)
{
ll l=sum[i],r=sum[n]-sum[n-i];
if(l>r) swap(l,r);
ans+=r-l+1;
if(i+dd<=n)
{
r=min(r,sum[n]-sum[n-i-dd]-xx);
l=max(l,sum[i+dd]-xx);
ans-=max(0ll,r-l+1);
}
}
}
printf("%lld\n",ans);
}