1024 数字0-9的数量
题目链接:
http://www.51nod.com/Challenge/Problem.html#problemId=1042
Hint(方法1):solve(r)-solve(l-1)、分成首位,中间位,末位瞎搞就好
Hint(方法2):数位dp
/*
2019/11/4
方法1
(懒得再开一个数组
直接在solve函数里求完了ans[r]-ans[l-1]
导致了代码非常冗长2333
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll le,ri;
ll dp[15];
ll solve()
{
ll rt=0,lt=0,sr=1,sl=1;
bool f1=true,f2=true;
while(ri)
{
if(ri<10)
{
for(int i=1;i<ri;i++)
{
dp[i]+=sr;
}
dp[ri]+=rt+1;
break;
}//首位
int a=ri%10;
ri/=10;
if(f1)
{
for(int i=1;i<=a;i++)
dp[i]++;
for(int i=0;i<=9;i++)
dp[i]+=ri;
}//末位
else
{
if(a!=0)
dp[0]+=ri*sr;
for(int i=1;i<a;i++)
dp[i]+=(ri+1)*sr;
if(a!=0)
dp[a]+=ri*sr+rt+1;
else
{
dp[a]+=(ri-1)*sr+rt+1;
}
for(int i=a+1;i<=9;i++)
dp[i]+=ri*sr;
}//中间位
rt+=sr*a;sr*=10;
f1=false;
}
while(le)
{
if(le<10)
{
for(int i=1;i<le;i++)
{
dp[i]-=sl;
}
dp[le]-=(lt+1);
break;
}//首位
int a=le%10;
le/=10;
if(f2)
{
for(int i=1;i<=a;i++)
dp[i]--;
for(int i=0;i<=9;i++)
dp[i]-=le;
}//末位
else
{
if(a!=0)
dp[0]-=le*sl;
for(int i=1;i<a;i++)
dp[i]-=(le+1)*sl;
if(a!=0)
dp[a]-=(le*sl+lt+1);
else
{
dp[a]-=((le-1)*sl+lt+1);
}
for(int i=a+1;i<=9;i++)
dp[i]-=le*sl;
}//中间位
lt+=sl*a;sl*=10;
f2=false;
}
}
int main()
{
scanf("%lld%lld",&le,&ri);
le--;
solve();
for(int i=0;i<=9;i++)
{
printf("%lld\n",dp[i]);
}
return 0;
}
/*
2019/11/11
方法2
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll dp1[25],dp2[25];
void dfs(ll x,ll sx,ll ans[])
{
int a=x%10;x/=10;ll t=x;
for(int i=1;i<=a;i++) ans[i]+=sx;
for(int i=0;i<10;i++) ans[i]+=sx*x;
while(t)
{
ans[t%10]+=sx*(a+1);
t/=10;
}
if(x)
dfs(x-1,sx*10,ans);
}
int main()
{
ll le,ri;
scanf("%lld%lld",&le,&ri);
le--;
dfs(ri,1,dp1);dfs(le,1,dp2);
for(int i=0;i<10;i++) printf("%lld\n",dp1[i]-dp2[i]);
return 0;
}
1100 斜率最大
题目链接:
http://www.51nod.com/Challenge/Problem.html#problemId=1100
Hint(437ms):暴力可过,很久以前写的代码懒得重写了当时maxn初始化设大了一直wa,现在debug完ac
Hint(优化,31ms):可以把优化到(虽然差不多是这个意思,但这个复杂度是我在胡说八道,没有这么求复杂度的23333),咳,实际上我们很容易发现取相邻两个点最优:
←以及有一种需要考虑的特殊情况(同直线多解)
提供一个数据:
INPUT:
5
1 2
2 4
3 6
4 2
5 4
OUTPUT:
1 2
1 3
2 3
4 5
/*
2019/11/24
暴力
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
struct P
{
ll x,y;
int f;
}point[10005];
bool cmp(P a,P b)
{
if(a.x<=b.x) return true;
else return false;
}
vector<pair<P,P> > v;
bool cmp2(pair<P,P> a,pair<P,P> b)
{
if(a.first.x<b.first.x) return true;
else return false;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&point[i].x,&point[i].y);
point[i].f=i;
}
sort(point+1,point+1+n,cmp);
double maxn=-2e10;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
//cout<<'i'<<i<<' '<<'j'<<j<<endl;
double k=(point[j].y-point[i].y)*1.0/(point[j].x-point[i].x);
//cout<<k<<endl;
//cout<<maxn<<endl;
if(k>=maxn)
{
if(k>maxn) v.clear();
pair<P,P> it;
it.first=point[i];
it.second=point[j];
v.push_back(it);
maxn=k;
}
}
}
//sort(v.begin(),v.end(),cmp2);
//cout<<v.size()<<endl;
for(int i=0;i<v.size();i++)
printf("%d %d\n",v[i].first.f,v[i].second.f);
return 0;
}
/*
2019/11/24
优化
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
struct P
{
ll x,y;
int f;
} point[10005];
bool cmp(P a,P b)
{
if(a.x<=b.x) return true;
else return false;
}
vector<pair<P,P> > v;
bool cmp2(pair<P,P> a,pair<P,P> b)
{
if(a.first.x<b.first.x) return true;
else return false;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%lld%lld",&point[i].x,&point[i].y);
point[i].f=i;
}
sort(point+1,point+1+n,cmp);
double maxn=-2e10;
int step=0;
for(int i=1; i<=n-1; i++)
{
double k=(point[i+1].y-point[i].y)*1.0/(point[i+1].x-point[i].x);
if(k>=maxn)
{
pair<P,P> it;
if(k>maxn)
{
v.clear();
step=1;
}
else
{
for(int j=1;j<=step;j++)
{
it.first=point[i-j];
it.second=point[i+1];
v.push_back(it);
}
step++;
}
it.first=point[i];
it.second=point[i+1];
v.push_back(it);
maxn=k;
}
else step=0;
}
sort(v.begin(),v.end(),cmp2);
//cout<<v.size()<<endl;
for(int i=0; i<v.size(); i++)
printf("%d %d\n",v[i].first.f,v[i].second.f);
return 0;
}
1103 N的倍数
题目链接:
http://www.51nod.com/Challenge/Problem.html#problemId=1103
Hint:前缀和、抽屉原理
/*
2019/11/6
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll a[50005];
int vis[50005];
int main()
{
int n;
ll sum=0;
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%I64d",a+i);
}
for(int i=1; i<=n; i++)
{
sum+=a[i];
sum%=n;
if(sum==0)
{
printf("%d\n",i);
for(int j=1; j<=i; j++)
{
printf("%I64d\n",a[j]);
}
break;
}
if(vis[sum]!=0)
{
printf("%d\n",(i-vis[sum]));
for(int j=vis[sum]+1; j<=i; j++)
{
printf("%I64d\n",a[j]);
}
break;
}
vis[sum]=i;
}
return 0;
}
1125 交换机器的最小代价
题目链接:
http://www.51nod.com/Challenge/Problem.html#problemId=1125
Hint:贪心(环内最小 or 环外最小)
/*
2019/11/26
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
pair<ll,int> wi[50005];
int f[50005];
int tf[50005];
bool vis[50005];
bool cmp(int x,int y)
{
if(wi[x].first<wi[y].first)
return true;
else if(wi[x].first==wi[y].first)
{
return wi[x].second<wi[y].second;
}
else
return false;
}
int main()
{
int n;
scanf("%d",&n);
ll mint=1e9;
for(int i=1; i<=n; i++)
{
scanf("%lld",&wi[i].first);
mint=min(mint,wi[i].first);
wi[i].second=i;
f[i]=i;
}
sort(f+1,f+n+1,cmp);
for(int i=1; i<=n; i++)
tf[f[i]]=i;
ll ans=0;
for(int i=1;i<=n;i++)
{
if(tf[i]!=i && !vis[tf[i]])
{
int j=tf[i];
int step=0;ll minn=1e9;
while(!vis[j])
{
ans+=wi[f[j]].first;
step++;
minn=min(minn,wi[f[j]].first);
vis[j]=true;
j=tf[j];
}
ll t1=minn*(step-2),t2=mint*(step-1)+mint*2+minn;
if(t1<t2)
ans+=t1;
else
ans+=t2;
}
}
printf("%lld\n",ans);
return 0;
}
1132 覆盖数字的数量
题目链接:
http://www.51nod.com/Challenge/Problem.html#problemId=1132
Hint:数学瞎推(考虑之间空出来的数有多少个,等差数列求和)、分类
/*
2019/12/7
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll a,b,x,y;
scanf("%lld%lld%lld%lld",&a,&b,&x,&y);
if(a==b)
{
ll hmx=(x-1)/a;
ll hmy=y/a;
printf("%lld\n",hmy-hmx);
}
else
{
ll k=a/(b-a);
if(a%(b-a)!=0) k++;
if(k<2)
{
ll ans=y-x+1;
if(x<a)
{
ans-=(a-x);
}
ans=max(ans,0LL);
printf("%lld\n",ans);
}
else
{
ll ans=y-x+1;
if(x<a)
{
ans-=(a-x);
}
ll st=x/a;
st=max(st,1LL);
ll en=y/b;
ll edge=a/(b-a);
if(a%(b-a)!=0) edge++;
en=min(en,edge);
st++;
if(en>=st)
{
//st++;
ll sum1=0;
if((st+en)%2==0)
sum1=((st+en)/2)*(en-st+1);
else
sum1=((en-st+1)/2)*(st+en);
ll sum2=sum1-(en-st+1);
sum1*=a;
sum2*=b;
//cout<<sum1-sum2<<endl;
ans-=(sum1-sum2-1);
}
printf("%lld\n",ans);
}
}
}
return 0;
}
1191 消灭兔子
题目链接:
http://www.51nod.com/Challenge/Problem.html#problemId=1191
Hint:贪心(血量高→血量低)、优先队列
/*
2019/11/29
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int b[100005];
priority_queue<int,vector<int>,greater<int> > pq;
pair<int,int> p[100005];//first:p second:d
bool cmp(int x,int y)
{
return x>y;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
}
sort(b+1,b+n+1,cmp);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&p[i].first,&p[i].second);
}
sort(p+1,p+m+1);
int step=m;
ll ans=0;
bool flag=false;
for(int i=1;i<=n;i++)
{
int minn=1000001;
while(step>=1 && p[step].first>=b[i])
{
if(p[step].second<=minn)
{
if(minn!=1000001)
{
pq.push(minn);
}
minn=p[step].second;
}
else
{
int x=p[step].second;
pq.push(x);
}
step--;
}
if(!pq.empty())
{
int mint=pq.top();
if(mint<minn)
{
pq.pop();
if(minn!=1000001)
pq.push(minn);
minn=mint;
}
}
if(minn==1000001)
{
flag=true;
break;
}
ans+=minn;
}
if(flag)
printf("No Solution\n");
else
printf("%lld\n",ans);
return 0;
}
1262 扔球
题目链接:
http://www.51nod.com/Challenge/Problem.html#problemId=1262
Hint:数论、考虑间隔点
/*
2019/12/3
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
int x;
scanf("%d",&x);
x++;
int ans=x;
if(x%2==0)
{
while(x%2==0)
x/=2;
ans/=2;
}
for(int i=3;i<=sqrt(x);i+=2)
{
if(x%i==0)
{
while(x%i==0)
x/=i;
ans/=i;ans*=(i-1);
}
}
if(x>2)
{
ans/=x;ans*=(x-1);
}
printf("%d\n",ans);
return 0;
}
1419 最小公倍数挑战
题目链接:
http://www.51nod.com/Challenge/Problem.html#problemId=1419
Hint:推规律(相邻两奇数互质、相邻两数互质、偶奇互质情况判断)
/*
2019/12/4
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
int n;
scanf("%d",&n);
if(n<=2) printf("%d\n",n);
else if(n%2) printf("%lld\n",(ll)n*(n-1)*(n-2));
else if(n%3) printf("%lld\n",(ll)n*(n-1)*(n-3));
else
{
printf("%lld\n",(ll)(n-1)*(n-2)*(n-3));
}
return 0;
}
1445 变色DNA
题目链接:
http://www.51nod.com/Challenge/Problem.html#problemId=1445
Hint:最短路(暂时只写了floyd版,之后有时间再补上dijkstra,应该都没差因为数据很小。。)
/*
2019/11/25
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int dis[55][55];
char pic[55][55];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%s",pic[i]);
for(int j=0; j<n; j++)
{
dis[i][j]=1e4;
if(i==j)
dis[i][j]=0;
}
}
for(int i=0; i<n; i++)
{
int step=0;
for(int j=0; j<n; j++)
{
if(pic[i][j]=='Y')
{
dis[i][j]=step++;
}
}
}
for(int k=0; k<n; k++)
{
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
printf("%d\n",(dis[0][n-1]==1e4?dis[0][n-1]=-1:dis[0][n-1]));
}
return 0;
}
2200 接水问题二
题目链接:
http://www.51nod.com/Challenge/Problem.html#problemId=2200
Hint:贪心、推公式
/*
2019/12/10
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
struct Point
{
int x,y;
double a;
bool operator <(const Point & t) const
{
return a>=t.a;
}
} po[100005];
int main()
{
int n;
scanf("%d",&n);
int cnt=0;
for(int i=1; i<=n; i++)
{
int xx,yy;
scanf("%d%d",&xx,&yy);
if(xx==0||yy==0) continue;
++cnt;
po[cnt].x=xx;
po[cnt].y=yy;
po[cnt].a=1.0*po[cnt].x/po[cnt].y;
}
sort(po+1,po+cnt+1);
ll suma=0,ans=0;
for(int i=1; i<=cnt; i++)
{
suma+=po[i].y;
ans+=suma*po[i].x;
}
printf("%lld\n",ans);
return 0;
}
2463 旅行
题目链接:
http://www.51nod.com/Challenge/Problem.html#problemId=2463
Hint:贪心、搜索+剪枝(注意m只可能为n-1或n,即不存在环/存在一个环)
(今天晚上代码写得感觉很乱,假如我还记得的话再回来重写一遍。。
/*
2019/12/2
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
vector<int> v[5005];
int st[5005];
int vt[5005];
int top=0;
int tot=0;
int pre[5005];
bool vis[5005];
int n,m;
int xx=0,yy=0;
int step=1;
int ans[5005];
bool f=false;
bool flag=false;
void dfs(int x)
{
if(!vis[x])
{
if(x<ans[step])
flag=true;
if(x>ans[step]&&!flag)
{
return;
}
ans[step]=x;
}
if(step==n)
{
return;
}
vis[x]=true;
int minn=n+1;
int hm=0;
for(int i=0;i<v[x].size();i++)
{
int y=v[x][i];
if(!(y==yy&&x==xx)&&!(y==xx&&x==yy)&&!vis[y])
{
minn=min(minn,y);
hm++;
}
}
if(hm!=0)
{
step++;
pre[minn]=x;
dfs(minn);
}
else
{
dfs(pre[x]);
}
}
void dfs2(int x)
{
if(f) return;
st[++top]=x;
vis[x]=true;
for(int i=0;i<v[x].size();i++)
{
int y=v[x][i];
if(y==pre[x]) continue;
if(!vis[y])
{
pre[y]=x;
dfs2(y);
}
else
{
//cout<<x<<' '<<y<<"!!!"<<endl;
for(int j=top;st[j]!=y;j--)
{
vt[++tot]=st[j];
}
vt[++tot]=y;
f=true;
break;
}
}
if(f) return;
top--;
vis[x]=false;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
for(int i=1;i<=n;++i)
ans[i]=n+1;
if(m==n-1)
{
dfs(1);
for(int i=1;i<=n;++i)
printf("%d%c",ans[i],(i==n)?'\n':' ');
}
else
{
vis[1]=true;
dfs2(1);
vt[tot+1]=vt[1];
for(int i=1;i<=tot;++i)
{
xx=vt[i];yy=vt[i+1];
memset(vis,false,sizeof(vis));
flag=false;
step=1;
dfs(1);
}
for(int i=1;i<=n;++i)
printf("%d%c",ans[i],(i==n)?'\n':' ');
}
return 0;
}
2488 矩形的面积
题目链接:
http://www.51nod.com/Challenge/Problem.html#problemId=2488
Hint:随便画一画就知道有交集是啥情况了
/*
2019/11/19
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
ll a,b,c,d,e,f,g,h;
scanf("%lld%lld%lld%lld%lld%lld%lld%lld",&a,&b,&c,&d,&e,&f,&g,&h);
if((a<=g&&b<=h&&e<=c&&f<=d)||(a>=g&&b>=h&&e>=c&&f>=d))
{
ll lx,ly,rx,ry;
lx=max(a,e);ly=max(b,f);
rx=min(c,g);ry=min(d,h);
ll ans=(c-a)*(d-b);
ans-=(ry-ly)*(rx-lx);
ans+=(g-e)*(h-f);
printf("%lld\n",ans);
}
else
{
ll ans=(c-a)*(d-b)+(g-e)*(h-f);
printf("%lld\n",ans);
}
return 0;
}