A模拟
题意:A、B两队轮流罚球,共10局,告诉你罚球的结果,进球多的队伍获胜,问在哪一局就可以知道最终结果。
思路:枚举每一轮i,计算后面A、B队最好得分,若A最差>B最好||B最差>A最好,则可以判断胜负了。
#include <bits/stdc++.h>
#define lowbit(x) x & (-x)
#define ios cin.sync_with_stdio(false)
#define PII pair<int, int>
typedef long long ll;
const int N = 1e6 + 10;
const int inf = 0x3f3f3f3f;
using namespace std;
string s;
void solve()
{
cin >> s;
int a = 0, b = 0;
for (int i = 0; i < 10; i++)
{
if (s[i] == '1')
{
if (i & 1)
b++;
else
a++;
}
if (i & 1)
{
if (b > (9 - i) / 2 + a || a > (9 - i) / 2 + b)
{
cout << i + 1 << '\n';
return;
}
}
else
{
if (a > (10 - i) / 2 + b || b > (9 - i) / 2 + a)
{
cout << i + 1 << '\n';
return;
}
}
}
cout << -1 << '\n';
}
int main()
{
// ios;
int _t = 1;
cin >> _t;
while (_t--)
solve();
system("pause");
return 0;
}
L数学
题意:
思路:最佳策略就是依次猜, 先猜出团,在猜出团里的人;
猜团:5个团,第1次猜中概率是0.2,第二次是0.2,第三次是 0.2,第四次是0.4;
猜人:4个人,第一次是0.25,第二次是0.25,第三次是0.5;
最终答案:32(5.05)
C思维
题意:有n篇论文,n个教授,告诉你每篇论文的引用量,定义一位教授的H指数为使得"该教授发表的所有论文中,有至少H篇论文的引用量大于等于H"这一命题成立的最大的H。问最大的ΣHi
思路:注意到H指数不可能多于总的引用非0论文数,所以一人发一篇,此时答案最大,为引用非0论文数
#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define ios cin.sync_with_stdio(false)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
int n;
void solve()
{
cin>>n;
int ans=0;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
if(x>0) ans++;
}
cout<<ans<<'\n';
}
int main()
{
//ios;
int _t=1;
cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}
H思维
题意:有n*n块拼图,每块拼图的四条边可以是平、凹、凸,一块拼图的成本是10-凹的次数+凸的次数。告诉你n*n-1块拼图的形状,求缺失那块的成本。
思路:注意到凸凹是成对出现的,所以n*n块中凹次数=凸次数,统计前n*n-1块拼图凹和凸的次数,即可算出最后一块的凹凸个数。
#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define ios cin.sync_with_stdio(false)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
int n;
void solve()
{
cin>>n;
string s;
int cnt1=0,cnt2=0;
for(int i=1;i<=n*n-1;i++)
{
cin>>s;
for(int j=0;j<4;j++)
{
if(s[j]=='1') cnt1++;
else if(s[j]=='2') cnt2++;
}
}
cout<<10+(cnt1-cnt2)<<'\n';
}
int main()
{
//ios;
int _t=1;
cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}
D数学、分类讨论
题意:定义两个矩形A,B的IOU为两个矩形交集部分的面积除以两个矩形并集部分的面积。
现在,给出一个由平面上两点(0,0),(x,y)所确定的矩形和一个点P(px,py)。请你求出在所有以P点作为其中一个顶点且边都平行于坐标轴的矩形中,可以使其取到的最大IOU为多少。
思路:
#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define ios cin.sync_with_stdio(false)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
void solve()
{
int x,y,px,py;
cin>>x>>y>>px>>py;
if((px==0&&py==y)||(px==x&&py==0)||(px==x&&py==y))
{
double ans=1;
printf("%.6f\n",ans);
return ;
}
if(px==x&&py<y)
{
int m=max(y-py,py);
double ans=(1.0*px*m)/(x*y);
printf("%.6f\n",ans);
return ;
}
if(py==y&&px<x)
{
int m=max(x-px,px);
double ans=(1.0*m*py)/(x*y);
printf("%.6f\n",ans);
return ;
}
if(px==x||py==y)
{
double ans=(1.0*x*y)/(px*py);
printf("%.6f\n",ans);
return ;
}
if(px>x&&py>y)
{
double ans=(1.0*x*y)/(px*py);
printf("%.6f\n",ans);
return ;
}
if(px<x&&py<y)
{
double s=max({1.0*px*py,1.0*px*(y-py),1.0*(x-px)*py,1.0*(x-px)*(y-py)});
double ans=(s)/(x*y);
printf("%.6f\n",ans);
return ;
}
if(px<x&&py>y)
{
int m=max(px,x-px);
double ans=(1.0*m*y)/(x*y+(py-y)*m);
printf("%.6f\n",ans);
return ;
}
if(px>x&&py<y)
{
int m=max(py,y-py);
double ans=(1.0*x*m)/(x*y+(px-x)*m);
printf("%.6f\n",ans);
return ;
}
}
int main()
{
//ios;
int _t=1;
cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}
M DP
题意:共n朋友,现在有m个仙贝,若当前还剩下x(x>0)个仙贝,并给了一位朋友y个仙贝(x,y都为整数),则这位朋友的好感度将增加y/x(这个值可以为小数)。求所有人的好感度之和最大为多少
思路:f [ i ][ j ]表示已经给𝑖个人分了仙贝,分出去了共𝑗个收获的最大好感度是多少.枚举第 𝑖 个人分到的仙贝数k.
#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define ios cin.sync_with_stdio(false)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
int n,m;
double f[510][510];
void solve()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
for(int k=0;k<=j;k++)
f[i][j]=max(f[i][j],f[i-1][j-k]+(1.0*k)/(m-(j-k)));
printf("%.8f\n",f[n][m]);
}
int main()
{
//ios;
int _t=1;
//cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}
K贪心
题意:
思路:
通过手玩小样例,发现类似1001001001……11111这样的串(也就是密的部分全是1,松的部分一个1占多数的区间都没有)比较优;
#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define ios cin.sync_with_stdio(false)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
int n,m;
void solve()
{
cin>>n>>m;
int M=m;
int ans=(n+2)/3;
if(m<=ans||n<3)
{
cout<<0<<'\n';
return ;
}
m-=ans;
int cnt=0;
if(n%3==0)
{
if(m>0)
{
m--;
cnt++;
if(m>0) m--,cnt++;
int r=m%2;
cnt+=m/2*3;
m-=m/2*2;
if(r==1) cnt+=2,m--;
}
}
else if(n%3==1)
{
int r=m%2;
cnt+=m/2*3;
m-=m/2*2;
if(r==1) cnt+=2,m--;
}
else
{
if(m>0)
{
m--;
cnt++;
int r=m%2;
cnt+=m/2*3;
m-=m/2*2;
if(r==1) cnt+=2,m--;
}
}
if(n==M) cnt--;
cout<<cnt<<'\n';
}
int main()
{
//ios;
int _t=1;
//cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}
G性质、数据结构
题意:
思路:
性质:𝑓(𝑥)经过不多次数的操作会收敛到一个不变的值𝑓(𝑥0) = 𝑥0;
𝑥0有三个:0、99、100; 即,总操作次数不大;
用set存所有未到达x0的下标
#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define ios cin.sync_with_stdio(false)
#define PII pair<int,int>
typedef long long ll;
const int N=1e5+10;
const int inf=0x3f3f3f3f;
using namespace std;
int n,m;
ll a[N];
int f(ll x)
{
return round(10*sqrt(x));
}
void solve()
{
cin>>n>>m;
ll ans=0;
set<int>st;
for(int i=1;i<=n;i++)
{
cin>>a[i];
ans+=a[i];
if(f(a[i])!=a[i]) st.insert(i);
}
st.insert(n+1);
for(int i=1;i<=m;i++)
{
int op;
cin>>op;
if(op==1)
{
int l,r,k;
cin>>l>>r>>k;
int pos=l;
while(1)
{
int nex=*st.lower_bound(pos);
if(nex>r) break;
for(int _=1;_<=min(k,20);_++)
{
ans-=a[nex];
a[nex]=f(a[nex]);
ans+=a[nex];
}
if(f(a[nex])==a[nex]) st.erase(nex);
pos=nex+1;
}
}
else cout<<ans<<'\n';
}
}
int main()
{
//ios;
int _t=1;
//cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}
F思维 DFS
题意:
思路:
注意到对于一个大小为𝑠𝑧的联通块,无论块内的炸蛋如何放置, 这个联通块任意两点作为起点终点的𝑠𝑧 ∗ 𝑠𝑧种所有方案都可以做到
证明:考虑联通块是一颗树的情况,可以先从S不放炸蛋的走到T,然后 从T出发,按照类似dfs的方式遍历这棵树,在回溯时选择放炸蛋即可做到放完所有炸蛋最终回到T。
因此,记第 i 个联通块的大小为𝑠𝑧𝑖,有炸蛋的联通块数量为B, 则:
• B=0:输出Σ𝑠𝑧𝑖^2;
• B=1:输出有炸弹联通块𝑗的𝑠𝑧𝑗^2;
• B>=2:无解,输出0
#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define ios cin.sync_with_stdio(false)
#define PII pair<int,int>
typedef long long ll;
const int N=1e5+10,M=2e5+10;
const int inf=0x3f3f3f3f;
using namespace std;
int n,m;
vector<int>g[N];
int bomb[N];
bool st[N];
bool has_bomb;
int dfs(int u)
{
int ret=1;
st[u]=1;
if(bomb[u]) has_bomb=1;
for(int i=0;i<g[u].size();i++)
{
int j=g[u][i];
if(!st[j])
{
ret+=dfs(j);
}
}
return ret;
}
void solve()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
for(int i=1;i<=n;i++)
{
scanf("%d",&bomb[i]);
}
int B=0;
int last_bomb=-1;
vector<ll>g_sz;
for(int i=1;i<=n;i++)
{
if(!st[i])
{
has_bomb=0;
int sz=dfs(i);
g_sz.push_back(sz);
if(has_bomb) B++,last_bomb=((int)g_sz.size())-1;
}
}
ll ans=0;
if(B==0)
{
for(int i=0;i<g_sz.size();i++)
ans+=(ll)g_sz[i]*g_sz[i];
}
else if(B==1)
{
ans=(ll)g_sz[last_bomb]*g_sz[last_bomb];
}
else ans=0;
printf("%lld\n",ans);
}
int main()
{
//ios;
int _t=1;
//cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}
E计算几何 叉积
题意:
思路:注意到操作3和操作1、2的不同之处,操作3可以使铁丝沿AB或BC翻转,这可以使用叉积来判断。先将AB、BC和ED、EF按照长度进行匹配,找到ABC与DEF 的关系,假设ABC与DEF一一对应,则cross(AB,BC)与cross(DE,EF) 正负性不同时,说明一定进行了操作3,cross为叉乘。特别的,AB和BC长度相等时无法判断,总是no;
#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define ios cin.sync_with_stdio(false)
#define PDD pair<double,double>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
const double eps = 1e-5;
using namespace std;
PDD A,B,C,D,E,F;
double len(PDD a)
{
return a.first*a.first+a.second*a.second;
}
double cross(PDD a,PDD b)
{
return a.first*b.second-b.first*a.second;
}
void solve()
{
cin>>A.first>>A.second>>B.first>>B.second>>C.first>>C.second;
cin>>D.first>>D.second>>E.first>>E.second>>F.first>>F.second;
PDD AB={B.first-A.first,B.second-A.second},BC={C.first-B.first,C.second-B.second};
PDD DE={E.first-D.first,E.second-D.second},EF={F.first-E.first,F.second-E.second};
if(fabs(len(AB)-len(BC))<eps)
{
puts("NO");
return ;
}
if(fabs(len(AB)-len(DE))<eps) ;
else if(fabs(len(AB)-len(EF))<eps) swap(AB,BC);
double c1=cross(AB,BC);
double c2=cross(DE,EF);
if(c1*c2<0) puts("YES");
else puts("NO");
}
int main()
{
//ios;
int _t=1;
cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}