8.16-8.19学习笔记(三场比赛)
作者:互联网
8.16-8.19学习笔记
2019年我能变强组队训练赛第四场8.16
纪念一下这个差点被hack的比赛
G题
题目比较水,主要是理解,用了排序。其他就是按照题目敲
#include<bits/stdc++.h>
using namespace std;
struct node{
int a,t,v;
}s[11000];
bool cmp(node x,node y){
return x.a>y.a;
}
int main(){
int n;
scanf("%d",&n);
double s1=0;
int v1=0;
for(int i=1;i<=n;i++){
scanf("%d%d",&s[i].a,&s[i].t);
s[i].v=s[i].a*s[i].t;
s1+=v1*s[i].t+0.5*s[i].a*s[i].t*s[i].t;
v1+=s[i].v;
}
sort(s+1,s+n+1,cmp);
double s2=0;
int v2=0;
for(int i=1;i<=n;i++){
s2+=v2*s[i].t+0.5*s[i].a*s[i].t*s[i].t;
v2+=s[i].a*s[i].t;
}
double ans=s2-s1;
printf("%.1lf\n",ans);
return 0;
}
K题
题目比较好理解-还原原序列;
就因为这个差点领了盒饭。
画个图,思路就有了。
举个例子!
将第一维的最大上升序列的下标记在第二维(用于记录原来的位置):
第一维x: 1 1 2 3 3 2 1 1
第二维num:1 2 3 4 5 6 7 8
按第一维排序:
x: 1 1 1 1 2 2 3 3
num:1 2 7 8 3 6 4 5
第三维:8 7 6 5 4 3 2 1(倒序填入对应的x)
为了将x变回原本的位置
将整个结构体按num再次排序
返回原本的顺序
x:1 1 2 3 3 2 1 1
num:1 2 3 4 5 6 7 8
r: 8 7 4 2 1 3 6 5
输出的第三维就是答案
#include<bits/stdc++.h>
using namespace std;
struct P
{
int x,num,r;
};
bool cmp1(P a,P b) //第一次比较
{
if(a.x!=b.x)
return a.x<b.x;
return a.num<b.num;
}
bool cmp2(P a,P b)
{
return a.num<b.num;
}
int main()
{
struct P s[100005]= {0};
int n,i,x,t;
scanf("%d",&n);
for(i=1; i<=n; i++)
{
scanf("%d",&t);
s[i].num=i;
s[i].x=t;
}
sort(s+1,s+1+n,cmp1);
int k=n;
for(i=1; i<=n; i++)
{
s[i].r=k;
k--;
}
sort(s+1,s+1+n,cmp2);
for(i=1;i<n;i++)printf("%d ",s[i].r);
printf("%d\n",s[n].r);
return 0;
}
J题
博弈论题目
本题的突破口在于1。分为以下几种情况讨论:
- 全是1的情况 如果n≡0(mod3),A是必输的,否则是必胜的。
- 只有一个不是1的情况,那么A是必胜的。因为如果n≡0(mod3),那么将不是1的那堆取成1,这样就相当于变成了n≡1(mod3)的必胜态。否则就按照情况1的方式取。
- 有两个不是1的情况:
首先我们可以知道,假如只有两堆,并且这两堆都不是1,那么A是必输的。如果加了m堆1,那么若m≡0(mod3),那么A必输(因为B,C总能取成n≡0(mod3)的状态)。如果不是,并且存在至少一堆是2,A必胜(余1将不是2的那一堆取成1,余2将不是2的那堆取完)。 - 对于大于等于3的情况,另外两个人总可以转为2的必败态。A是必败的。
对于博弈论来说,求特殊值和求出各种情况格外重要
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
int n;cin>>n;
int cnt1=0,cnt2=0;
for(int i=1;i<=n;i++){
int x;
cin>>x;
if(x==1)++cnt1;
else if(x==2)++cnt2;
}
if(cnt1==n-1)
cout<<"Win"<<endl;
else if(cnt1==n)
{
if(cnt1%3==0)
cout<<"Lose"<<endl;
else
cout<<"Win"<<endl;
}
else if(cnt1==n-2)
{
if((cnt2&&cnt1%3))
cout<<"Win"<<endl;
else cout<<"Lose"<<endl;
}
else cout<<"Lose"<<endl;
return 0;
}
A题
一直在试图搓出来的dp
尝试download 别人的思路
题目的意思是某人想按照输入长度为k的这个顺序看演唱会,输入长度为n的这个是所有的顺序,然后A-Z代表的是看演唱会之前需要在家至少待几天。
就可以考虑到dp[i][j]=dp[i+1][j]+dp[i+str1[i]-‘A’+1][j+1]
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
char str1[150];
char str2[100005];
int valu[30];
int dp[100005][105];
int main()
{
int n,k;
scanf("%d%d",&k,&n);
for(int i=0;i<26;i++)
scanf("%d",&valu[i]);
scanf("%s",str1+1);//k 需要比较的串
scanf("%s",str2+1);//n 母串
for(int i=n;i>=1;i--)//枚举最大的那个串
{
for(int j=k;j>=1;j--)//枚举比较的串
{
dp[i][j]=dp[i+1][j];
if(j==k && str1[j]==str2[i])//如果当前是最后一个 而且等于上边的那个
dp[i][j]=(dp[i][j]+1)%mod;
else if(i+valu[str2[i]-'A']+1<=n && str2[i]==str1[j])
dp[i][j]=(dp[i][j]+dp[i+valu[str2[i]-'A']+1][j+1])%mod;
}
}
printf("%d\n",dp[1][1]);
return 0;
}
2019牛客暑期多校训练营第10场 8.17
H题
这一场最水的题目
#include<bits/stdc++.h>
using namespace std;
int main()
{
int T;
cin >> T;
while (T--)
{
int a[7] = { 0 },c[7]={0};
int b[7][7] = { 0 };
int k,j,flag=0,ans=0,bns=0;
for (int i = 0; i < 5; i++)
{
cin >> k >> j;
b[j][k]=b[k][j] = 1;
a[k]++;
c[k]++;
c[j]++;
a[j]++;
if (a[j] == 3)
flag = j;
if (a[k] == 3)
flag = k;
}
sort(a, a + 7);
if (a[1] == 1 && a[2] == 1 && a[3] == 2 && a[4] == 2 && a[5] == 2 && a[6] == 2)
{
cout << "n-hexane" << endl;
continue;
}
if (a[1] == 1 && a[2] == 1 && a[3] == 1 && a[4] == 2 && a[5] == 2 && a[6] == 3)
{
for (int i = 1; i <= 6; i++)
{
if (b[flag][i] == 1)
{
if (c[i] == 1)
ans++;
if(c[i]==2)
bns++;
}
}
if(ans==2&&bns==1)
cout << "2-methylpentane" << endl;
else cout << "3-methylpentane" << endl;
continue;
}
if (a[1] == 1 && a[2] == 1 && a[3] == 1 && a[4] == 1 && a[5] == 3 && a[6] == 3)
{
cout << "2,3-dimethylbutane" << endl;
continue;
}
if (a[1] == 1 && a[2] == 1 && a[3] == 1 && a[4] == 1 && a[5] == 2 && a[6] == 4)
{
cout << "2,2-dimethylbutane" << endl;
continue;
}
}
return 0;
}
/*2
1 2
2 3
3 4
4 5
5 6
1 4
2 3
3 4
4 5
5 6
*/
B题
利用递归的性质
!!注意,数据很大,所以循环开到60!!
#include <bits/stdc++.h>
using namespace std;
long long len[505];
string x="COFFEE";string y="CHICKEN";
char f(int a,long long b){
if(a==1) return x[b-1];
if(a==2) return y[b-1];
else if(b<=len[a-2]) return f(a-2,b);
else return f((a-1),b-len[a-2]);//S(n-2):S(n-1) 如果处于的位置大于len【a-2】则该位置在S(n-1)之中
}
int main(){
len[1]=6;len[2]=7;
for(int i=3;i<=60;i++){
len[i]=len[i-1]+len[i-2];
}
int t;cin>>t;
while(t--){
int x;long long y;
cin>>x>>y;
if(x>60) x=60;
for(long long j=y;j<y+10;j++){
if(j>len[x]) break;//字符超限
cout<<f(x,j);
}
cout<<endl;
}
return 0;
}
2019年我能变强组队训练赛第五场 8.18
J题
水题 排序
#include<bits/stdc++.h>
using namespace std;
struct node{
string s;
int m;
}a[10050];
bool cmp(node x,node y){
return x.m>y.m;
}
int main(){
int n,d,k;
cin>>n>>d>>k;
for(int i=1;i<=n;i++) cin>>a[i].s>>a[i].m;
sort(a+1,a+n+1,cmp);
int tot=0,ans=0;
for(int i=1;i<=k;i++){
tot+=a[i].m;
ans++;
if(tot>=d){
break;
}
}
if(tot>=d) cout<<ans<<endl;
else cout<<"impossible"<<endl;
return 0;
}
C题
正向建图
#include<bits/stdc++.h>
using namespace std;
int a[1050][1050];
map<string,int>q;
int main(){
memset(a,0,sizeof(a));
int n,m;
string s1,s,s2;
int t=0;
cin>>n>>m;
for(int i=1;i<=n;i++){
int x=0,y=0;
cin>>s;
if(!q[s]) q[s]=++t;
x=q[s];
cin>>s;
cin>>s;
cin>>s;
cin>>s;
if(!q[s]) q[s]=++t;
y=q[s];
a[x][y]=1;//表示有边
}
for(int k=1;k<=t;k++)
for(int i=1;i<=t;i++)
for(int j=1;j<=t;j++)
a[i][j]=a[i][j]||(a[i][k]&&a[k][j]);//建图
for(int i=1;i<=m;i++){
int u=0,v=0;
cin>>s;
u=q[s];
cin>>s;
cin>>s;
cin>>s;
cin>>s;
v=q[s];
if(a[u][v]) cout<<"Fact\n";
else if(a[v][u]) cout<<"Alternative Fact\n";
else cout<<"Pants on Fire\n";
}
return 0;
}
F题
题意:
在点阵上,给出 N 个点的坐标(全部都是在格点上),将它们按顺序连接可以构成一个多边形,求该多边形内包含的格点的数目。
首先,根据皮克定理 S=a+2b−1,其中 S 是多边形面积,a 是多边形内部格点数目,b 是多边形边界上的格点数目。
那么,我们只要求出 S 和 b,就很好求得 a 了:
1、对于两端点(x1,y1),(x2,y2) 都再格点上的一条线段,该线段上的格点数目为 gcd(∣x1−x2∣,∣y1−y2∣)。这很好理解,对于横坐标差值和纵坐标差值求得的最大公因数 g,相当于将横坐标差值分成 g 份,由于是整除,因此显然每份的左右端点都是整数,对于纵坐标也是同样的道理,由于是最大公因数,所以不可能再分更多份,因此 gcd(|x1−x2|,|y1−y2|) 即求得两端点间最多能分成多少段由格点分割的线段,再加上 1 即整条线段上的格点数目。
2、对于格点按顺序给出的多边形,设P0=Pn+1 且 O 为原点,则面积为 21∑i=0n(OPi×OPi+1)。这个画个图模拟一下也非常容易理解。
皮克定理,小本本记下来
#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct node{
ll x,y;
}a[100050];
int main(){
int n;
ll s=0,b=0;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i].x>>a[i].y;
for(int i=1;i<=n;i++){
int t=0;
if(i+1>n) t=1;else t=i+1;
s+=a[i].x*a[t].y-a[i].y*a[t].x;
//s=os1^os2叉乘
b+=__gcd(abs(a[i].x-a[t].x),abs(a[i].y-a[t].y))+1;
}
b=b-n;//重复计算了两端点
cout<<(abs(s)-b+2)/2<<endl;
//s=a+b/2-1,s面积,b边界上点数,a多边形内点数
return 0;
}
持续学习ing
标签:三场,int,cin,long,include,8.19,using,8.16,dp 来源: https://blog.csdn.net/weixin_43786515/article/details/99720827