tag:签到
进制是效率最高的进制,越靠近e进制效率越高。
证明如下:
如果有一个n
位r
进制数,则表示这个数一共需要n*r
张牌
(成本),一共可以表示r^n
个数(回报),那么关于成本的式子
即:r*log(r,m)
m
是常量,对r/lnr求导,发现其在x=e
为极值点,则直接输出。
int x,y;
void solve()
{
cin>>x>>y;
if(x>y)swap(x,y);
if(x==2&&y==3)cout<<3<<endl;
else cout<<min(x,y)<<endl;
}
tag 数学,构造
构造 a i = a j a_i=a_j ai=aj, b i = − b j b_i=-b_j bi=−bj。
由题可知 a i + b i ≡ c i a_i+b_i\equiv c_i ai+bi≡ci, a j + b j ≡ c j a_j+b_j\equiv c_j aj+bj≡cj。
则 2 a i ≡ c i + c j 2a_i\equiv c_i+c_j 2ai≡ci+cj
分情况讨论:
const int N=1e5+10,mod=1e9+7;
int c[N];
int a[N],b[N];
int n,m;
void solve()
{
cin>>n>>m;
rep(i,0,n-1)cin>>c[i];
rep(i,0,n-1)
{
int t=n-i-1;
int x=(c[i]+c[t])%m;
if(x%2==0)x/=2;
else
{
if(m==2)
{
NO;
return;
}
x=(x+m)/2;
}
a[i]=x,a[t]=x;
b[i]=((c[i]-a[i])%m+m)%m;
b[t]=((c[t]-a[t])%m+m)%m;
}
YES;
for(int i=0;i<n;i++)cout<<a[i]<<' ';
cout<<endl;
for(int i=0;i<n;i++)cout<<b[i]<<' ';
}
tag: 01背包,简单题
问每个物品价值增加多少可以保证出现在01背包中。
所以我们先算出不要物品i
时,的最大价值,然后用maxv+1-当前价值就是最后结果
const int N=110;
int w[N],v[N];
int n,m;
int f[N];
int a[N];
void solve()
{
cin>>n>>m;
rep(i,1,n)cin>>v[i]>>w[i];
rep(i,1,n)
dwn(j,m,v[i])
f[j]=max(f[j],f[j-v[i]]+w[i]);
int maxv=f[m];
rep(k,1,n)
{
rep(i,1,m)f[i]=0;
rep(i,1,n)
{
if(i==k)continue;
dwn(j,m,v[i])
f[j]=max(f[j],f[j-v[i]]+w[i]);
}
if(maxv>f[m])a[k]=0;
else a[k]=maxv+1-f[m-v[k]]-w[k];
}
rep(i,1,n)cout<<a[i]<<endl;
}
tag 01背包前后缀优化
没有办法进行O(n^3),所以我们想办法将其进行优化。
f1[i][j]
存背包内存放前i
个物品,背包容量是j
的最优解
f2[i][j]
存背包内存放后i
个物品,背包容量是j
的最优解
思路是:必不选的最大价值-必选的价值+1
const int N=5010;
int w[N],v[N];
int f1[N][N],f2[N][N];
int a[N];
int n,m;
void solve()
{
cin>>n>>m;
rep(i,1,n)cin>>v[i]>>w[i];
rep(i,1,n)
{
rep(j,0,v[i]-1)f1[i][j]=f1[i-1][j];
rep(j,v[i],m)f1[i][j]=max(f1[i-1][j],f1[i-1][j-v[i]]+w[i]);
}
dwn(i,n,1)
{
rep(j,0,v[i]-1)f2[i][j]=f2[i+1][j];
rep(j,v[i],m)f2[i][j]=max(f2[i+1][j],f2[i+1][j-v[i]]+w[i]);
}
rep(i,1,n)
{
int res=0;
rep(j,0,m-v[i])//必选i
res=max(res,f1[i-1][j]+f2[i+1][m-v[i]-j]);
res+=w[i];
int sum=0;
rep(j,0,m)//必不选i
sum=max(sum,f1[i-1][j]+f2[i+1][m-j]);
a[i]=max(0ll,sum-res+1);
}
rep(i,1,n)cout<<a[i]<<endl;
cout<<endl;
}
signed main()
{
io;
int _;_=1;
//cin>>_;
while(_--)solve();
}
tag: 数学(二分)
枚举攻击次数。推数学公式即可
const int N=1e5+10;
int n,t,a;
int h[N],v[N];
void solve()
{
cin>>n>>t>>a;
rep(i,1,n)
cin>>h[i]>>v[i];
int res=0;
rep(i,1,n)
{
if(h[i]<=a)
res++;
else
{
if(a<=v[i]*t)
{
cout<<-1<<endl;
return;
}
int pre=h[i];
h[i]-=a;
res++;
res+=(h[i]+a-t*v[i]-1)/(a-t*v[i]);
}
}
cout<<1+(res-1)*t<<endl;
}
tag: 树状数组,树的遍历
/*
悲观看待成功,乐观看待失败。
author:leimingze
*/
#include
using namespace std;
const double pi = acos(-1);
const double eps=1e-7;
const int base=131;
#define YES cout<<"YES"<<endl
#define NO cout<<"NO"<<endl
#define x first
#define y second
#define int long long
#define lb long double
#define pb push_back
#define endl '\n'//交互题删掉此
#define all(v) (v).begin(),(v).end()
#define PII pair<int,int>
#define rep(i,x,n) for(int i=x;i<=n;i++)
#define dwn(i,n,x) for(int i=n;i>=x;i--)
#define ll_INF 0x7f7f7f7f7f7f7f7f
#define INF 0x3f3f3f3f
#define io ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
int Mod(int a,int mod){return (a%mod+mod)%mod;}
int lowbit(int x){return x&-x;}//最低位1及其后面的0构成的数值
int qmi(int a, int k, int p){int res = 1 % p;while (k){if (k & 1) res = Mod(res * a , p);a = Mod(a * a , p);k >>= 1;}return res;}
int inv(int a,int mod){return qmi(a,mod-2,mod);}
int lcm(int a,int b){return a*b/__gcd(a,b);}
int n,k,q;
int l,m,r;
int sz(int x)//包括x在内的x子树的节点个数
{
return (lowbit(x)<<1)-1;
}
bool is_left_child(int x)//判断x是否为其父节点的左孩子,lowbit(x)的前一位是0则是
{
return !(x&(lowbit(x)<<1));
}
int fa(int x)//求父亲节点
{
return is_left_child(x)?x+lowbit(x):x-lowbit(x);//如果是左孩子则其父节点是x-lowbit(x),否则x+lowbit(x)
}
int lch(int x)//求左孩子,把x的最低位1置0,把x的最低位1的下一位置为1 得到 左孩子
{
return x^lowbit(x)^(lowbit(x)>>1);
}
int rch(int x)
{
return x^(lowbit(x)>>1);//把x的最低位1的下一位置为1 得到右孩子
}
int VLR(int x)
{
int rt=n;
int pos=1;
while(rt!=x)
{
pos++;
if(x<rt)rt=lch(rt);
else
{
pos+=sz(lch(rt));
rt=rch(rt);
}
}
return pos;
}
int LRD(int x)
{
if(x==n)return n;
int rt=x;
int pos=sz(rt);
while(rt!=n)
{
if(rt==rch(fa(rt)))pos+=sz(lch(fa(rt)));
rt=fa(rt);
}
return pos;
}
void solve()
{
cin>>k>>q;
n=1ll<<k;
while(q--)
{
int x;
cin>>x;
cout<<VLR(x)<<' '<<x<<' '<<LRD(x)<<endl;
}
}
signed main()
{
io;
int _;_=1;
//cin>>_;
while(_--)solve();
}
tag:搜索,暴力
先预处理zngg到达每个点的时间,然后qcjj按照地标走
const int N=1010;
int n,m;
int startx,starty;
int q;
char g[N][N];
int dist[N][N];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
PII get(char c,int x,int y)
{
if(c=='L')
if(g[x][y-1]!='#')return {x,y-1};
if(c=='R')
if(g[x][y+1]!='#')return {x,y+1};
if(c=='U')
if(g[x-1][y]!='#')return {x-1,y};
if(c=='D')
if(g[x+1][y]!='#')return {x+1,y};
return {x,y};
}
void bfs()
{
queue<PII>q;
q.push({startx,starty});
dist[startx][starty]=0;
while(q.size())
{
auto t=q.front();
q.pop();
for(int i=0;i<4;i++)
{
int a=dx[i]+t.x,b=dy[i]+t.y;
if(a<0||a>=n||b<0||b>=m)continue;
if(g[a][b]=='#')continue;
if(dist[a][b]!=0x3f3f3f3f)continue;
dist[a][b]=dist[t.x][t.y]+1;
q.push({a,b});
}
}
}
int find(int x,int y)
{
int cnt=1;
int res=ll_INF;
while(cnt<=n*m)
{
auto t=get(g[x][y],x,y);
int a=t.x,b=t.y;
if(a==x&&b==y)
{
if(dist[a][b]==0x3f3f3f3f)
return -1;
}
if(dist[a][b]<=cnt)res=min(res,max(dist[a][b],cnt));
cnt++;
x=a,y=b;
}
return res;
}
void solve()
{
cin>>n>>m>>startx>>starty>>q;
rep(i,0,n-1)
rep(j,0,m-1)
cin>>g[i][j],dist[i][j]=0x3f3f3f3f;
bfs();
while(q--)
{
int x,y;
cin>>x>>y;
cout<<find(x,y)<<endl;
}
}
tag:签到
int va,vb,vc;
void solve()
{
cin>>va>>vb>>vc;
int a=vb+vc-va;
int b=va+vc-vb;
int c=va+vb-vc;
if(a%2||b%2||c%2)NO;
else if(a+b>c&&a+c>b&&b+c>a&&abs(a-b)<c&&abs(a-c)<b&&abs(b-c)<a)
{
YES;
cout<<a/2<<' '<<b/2<<' '<<c/2<<endl;
}
else NO;
}
tag:诈骗,签到
const int N=1e5+10;
int a[N];
int n;
void solve()
{
cin>>n;
a[1]=a[2]=1;
a[3]=2;
for(int i=4;i<=n;i+=3)
{
a[i]=a[i-3];
a[i+1]=a[i-2];
a[i+2]=a[i-1];
}
rep(i,1,n)cout<<a[i]<<' ';
cout<<endl;
}