根据题意列式,代值进入计算即可。
cin>>n>>m>>x>>t>>d;
if(m>=x)
printf("%d",t);
else
printf("%d",t-d*(x-m));
题目大意:求(a,b)逆时针旋转d度后的坐标。
利用c++提供的函数直接计算即可。
我们用acos(-1)作为圆周率派的精确值,用hypot(a,b)求斜边长,用atan2(b,a)求边与x轴夹角,就可以轻松求出答案了。
#include
#define ll long long
//const int N=1e6+5;
//const int N=1e5+5;
//const int mod=1e9+7;
//const long long mod=998244353;
const double pi=acos(-1.0);
using namespace std;
int n,t;
double a,b,d,x,y,l,theta;
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin>>a>>b>>d;
theta=atan2(b,a);
theta+=d*acos(-1)/180;
l=hypot(a,b);
x=l*cos(theta);
y=l*sin(theta);
printf("%.20f %.20f",x,y);
}
题目大意:给定一个字符串,问这个字符串a能否通过操作变成另外一个字符串b,这个字符串a如果有两个相同字母相连,就可以生成另外一个相同的字母。
用vector上的pair来分别保存两个字符串的信息,相当于将这两个字符串离散成只保存字母和个数信息。接着按照规则匹配即可,大概就是:
1.两个离散后字母数量要相等。
2.如果某个位置上字母b比a要多,那么a这个位置上的字母要大于1个。
3.不允许a的字母比b的多,因为字符串b并不能进行相同操作。
#include
#define ll long long
//const int N=1e6+5;
const int N=2e5+5;
//const int mod=1e9+7;
//const long long mod=998244353;
using namespace std;
int n,t,sum;
char a[N],b[N],c;
vector<pair<char,int>>u,v;
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin>>a+1;
cin>>b+1;
int lena=strlen(a+1);
int lenb=strlen(b+1);
for(int i=1;i<=lena;++i)
{
if(i==lena)
u.push_back({a[i],1});
if(a[i]!=a[i+1])
u.push_back({a[i],1});
else
{
c=a[i];
sum=0;
while(a[i]==c)
{
++i;
++sum;
}
--i;
u.push_back({c,sum});
}
}
for(int i=1;i<=lenb;++i)
{
if(i==lenb)
v.push_back({b[i],1});
if(b[i]!=b[i+1])
v.push_back({b[i],1});
else
{
c=b[i];
sum=0;
while(b[i]==c)
{
++i;
++sum;
}
--i;
v.push_back({c,sum});
}
}
//printf("%d %d\n",v.size(),u.size());
if(v.size()!=u.size())
{
printf("No\n");
return 0;
}
for(int i=0;i<u.size();++i)
{
if(u[i].first!=v[i].first)
{
printf("No\n");
return 0;
}
else if(u[i].second>v[i].second||(u[i].second==1&&v[i].second>1))
{
printf("No\n");
return 0;
}
}
printf("Yes\n");
}
题目大意:只通过给定的各个圆边,问某个圆上的点,是否能到达另外一个圆上的点。
我们通过几何关系检查两个圆之间是否相交,如果相交,则建立连接这两个圆编号的双向边。对于给出的点,我们判断它是否能走到另一个圆,必须满足的条件是这个编号能够通过dfs到达代表另一个点所在圆的编号。
#include
#define ll long long
const int N=1e6+5;
//const int N=1e5+5;
//const int mod=1e9+7;
//const long long mod=998244353;
using namespace std;
int n;
ll tx,ty,sx,sy;
ll x[N],y[N],r[N];
int a,b,vis[N];
vector<int>e[N];
ll dis(ll gx,ll gy,ll dx,ll dy)
{
return (gx-dx)*(gx-dx)+(gy-dy)*(gy-dy);
}
int dfs(int u)
{
vis[u]=1;
if(u==b)
return 1;
for(auto v:e[u])
{
if(vis[v])
continue;
if(dfs(v))
return 1;
}
return 0;
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin>>n;
cin>>sx>>sy>>tx>>ty;
for(int i=1;i<=n;++i)
cin>>x[i]>>y[i]>>r[i];
for(int i=1;i<=n;++i)
for(int j=i+1;j<=n;++j)
{
if(dis(x[i],y[i],x[j],y[j])>(r[i]+r[j])*(r[i]+r[j])||dis(x[i],y[i],x[j],y[j])<(r[i]-r[j])*(r[i]-r[j]))
continue;
e[i].push_back(j),e[j].push_back(i);
}
for(int i=1;i<=n;++i)
{
if(dis(sx,sy,x[i],y[i])==r[i]*r[i])
a=i;
if(dis(tx,ty,x[i],y[i])==r[i]*r[i])
b=i;
}
if(dfs(a))
printf("Yes\n");
else
printf("No\n");
}
题目大意:给出n个数字的质因数分解形式,问将任意一个数字变成1后,所有数字的最小公倍数的种类数。
很显然,最小公倍数是所有质数最大幂次的乘积,所以我们用pair将信息存下来,对某一个质因子,判断它是否是该质数的最大幂次,以及是否唯一,注意其它无贡献数字也会整体提供一个公倍数。
#include
#define ll long long
const int N=1e6+5;
//const int N=1e5+5;
//const int mod=1e9+7;
//const long long mod=998244353;
using namespace std;
int n,t,m;
int p,e;
map<int,int>mp,cnt;
vector<pair<int,int>>v[N];
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin>>n;
for(int i=1;i<=n;++i)
{
cin>>m;
while(m--)
{
cin>>p>>e;
v[i].push_back({p,e});
if(e>mp[p])
{
mp[p]=e;
cnt[p]=1;
}
else if(e==mp[p])
++cnt[p];
}
}
int ans=0,flag=0,flag2=0;
for(int i=1;i<=n;++i)
{
flag=0;
for(auto x:v[i])
{
if(mp[x.first]==x.second&&cnt[x.first]==1)
{
flag=1;
break;
}
}
if(flag)
++ans;
else
flag2=1;
}
if(flag2)
++ans;
printf("%d",ans);
}
题目大意:对于一个无向图,他的点有所连边数的限制,选择一些边,在满足限制的同时使边权尽可能大。
我们用 d p [ x ] [ 0 ] dp[x][0] dp[x][0]表示x选择了小于等于其限制 d [ u ] − 1 d[u]-1 d[u]−1条边的权值,用 d p [ i ] [ 1 ] dp[i][1] dp[i][1]表示选择了小于等于其限制的 d [ u ] d[u] d[u]的权值,如果有 d p [ x ] [ 0 ] + w > d p [ x ] [ 0 ] dp[x][0]+w>dp[x][0] dp[x][0]+w>dp[x][0]那么选择这条边是更优的情况,因此 d p [ y ] [ 0 ] + e [ i ] . w − d p [ y ] [ 1 ] dp[y][0]+e[i].w-dp[y][1] dp[y][0]+e[i].w−dp[y][1]就是选择这条边多获得的权值。每个节点应该由子节点 d p [ y ] [ 1 ] dp[y][1] dp[y][1]转移而来,如果 d [ x ] = = 0 d[x]==0 d[x]==0那么我们应该使 d p [ x ] [ 0 ] = − i n f dp[x][0]=-inf dp[x][0]=−inf。利用以上提到的性质即可完成dp。
#include
#define ll long long
const int N=1e6+5;
const long long inf=1e18;
//const int N=1e5+5;
//const int mod=1e9+7;
//const long long mod=998244353;
using namespace std;
int n,t;
int d[N];
int u,v;
ll w;
int head[N],cnt;
ll dp[N][2];
struct edge{
int next;
int to;
ll w;
}e[N];
void add(int from,int to,int w)
{
e[++cnt].next=head[from];
e[cnt].to=to;
e[cnt].w=w;
head[from]=cnt;
}
void dfs(int x,int fa)
{
vector<ll>k;
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].to;
if(y==fa)
continue;
dfs(y,x);
k.push_back(dp[y][0]+e[i].w-dp[y][1]);
dp[x][0]+=dp[y][1];
dp[x][1]+=dp[y][1];
}
sort(k.begin(),k.end(),greater<ll>());
int len=k.size();
for(int i=0;i<len;++i)
{
if(k[i]<0)
break;
if(i<d[x])
dp[x][1]+=k[i];
if(i<d[x]-1)
dp[x][0]+=k[i];
}
if(!d[x])
dp[x][0]=-inf;
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin>>n;
for(int i=1;i<=n;++i)
cin>>d[i];
for(int i=1;i<n;++i)
{
cin>>u>>v>>w;
add(u,v,w);
add(v,u,w);
}
dfs(1,0);
printf("%lld",dp[1][1]);
}
题目大意:给出一个数字矩阵,其中一个人可以选择某行,并将该行的数字加起来,另外一个人可以选择某列,同样可以将该列的数字加起来。特别的,如果两个人选择的交集在某一个负数上,就会获得一个无限小的负数。题目让我们求出最大可以获得的数字总和。
首先,如果我们什么都不选,那么有0作为答案,显然,获得无限小负数的方案应该被排除在外。接着,我们先贪心的将所有的正数全部选上求和,再考虑减去的情况。
这时,我们建立最小割模型:
1.将矩阵中的正数作为边权,连i到h+j的点,如果割去的话代表着两个人的选择重复。
2.将行的负数和作为边权,连s到i的点,如果割去代表不选该行。
3.将列的负数和作为边权,连h+j到t的点,如果割去代表不选该列。
4.那么,如何实现不出现无限小负数的情况呢,当负数出现时,连i到h+j的点,权值是无限小,因为我们求的是最小割,所以这条边必定会被割去,从而实现目的。
最后,我们将所有正数的和减去最小割便可得出答案。最小割的实现方式如代码所示。
#include
#define ll long long
//const int N=1e6+5;
const int N=5e4+5;
const ll inf=1e18;
//const int mod=1e9+7;
//const long long mod=998244353;
using namespace std;
int n,t;
ll a[305][305];
int s;
ll dis[N];
ll w,ans;
struct edge{
int next;
int to;
ll w;
}e[N];
int head[N],cnt=1;
void add(int from,int to,ll w)
{
e[++cnt].next=head[from];
e[cnt].to=to;
e[cnt].w=w;
head[from]=cnt;
}
bool bfs()
{
memset(dis,-1,sizeof(dis));
queue<int>q;
q.push(s);
dis[s]=0;
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].to;
if(dis[y]==-1&&e[i].w>0)
{
dis[y]=dis[x]+1;
q.push(e[i].to);
}
}
}
return dis[t]!=-1;
}
ll dfs(int x,ll k)
{
if(x==t)
return k;
ll flow=0,used=0;
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].to;
if(dis[y]==dis[x]+1&&e[i].w>0)
{
used=dfs(y,min(k,e[i].w));
if(!used)
continue;
flow+=used;
k-=used;
e[i].w-=used;
e[i^1].w+=used;
if(!k)
break;
}
}
if(!flow)
dis[x]=1;
return flow;
}
ll c[N],r[N],sum;
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
int h,w;
cin>>h>>w;
s=0,t=h+w+1;
for(int i=1;i<=h;++i)
for(int j=1;j<=w;++j)
cin>>a[i][j];
for(int i=1;i<=h;++i)
for(int j=1;j<=w;++j)
{
if(a[i][j]>=0)
{
add(i,h+j,a[i][j]);
add(h+j,i,0);
ans+=a[i][j];
}
else
{
add(i,h+j,-inf);
add(h+j,i,inf);
r[i]-=a[i][j];
c[j]-=a[i][j];
}
}
for(int i=1;i<=h;++i)
{
add(s,i,r[i]);
add(i,s,0);
}
for(int j=1;j<=w;++j)
{
add(h+j,t,c[j]);
add(t,h+j,0);
}
while(bfs())
sum+=dfs(s,inf);
printf("%lld\n",ans-sum);
}
`