E. 3-cycles
题意:
使得图中不存在长度为3的环,求满足条件的最多边的数目
题解:
二部图的任意两点的最小环长度大于3
#include<bits/stdc++.h>
#define mp make_pair
#define se second
#define fi first
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<ll, ll> pll;
typedef long double ld;
const int N=1e6+10;
const int MAXN=20010;
const int INF=0x3f3f3f3f;
const double eps=0.0000001;
const ll mod=998244353;
double n,m,x,y,z,k,cnt,t,len,q;
double a[N],b[N],c[N];
//scanf("%lld%lld",&n,&m);
//printf("%lld\n",ans);
//for(int i=1;i<=n;i++)
int main()
{
cin >> n ;
int M = n / 2 ;
cout << M * ( n - M ) << endl ;
for ( int i = 1 ; i <= M ; i ++ )
for ( int j = M + 1 ; j <= n ; j ++ )
cout << i << " " << j << endl ;
return 0 ;
}
D - 小兔的棋盘
题意:
小兔的叔叔从外面旅游回来给她带来了一个礼物,小兔高兴地跑回自己的房间,拆开一看是一个棋盘,小兔有所失望。不过没过几天发现了棋盘的好玩之处。从起点(0,0)走到终点(n,n)的最短路径数是C(2n,n),现在小兔又想如果不穿越对角线(但可接触对角线上的格点),这样的路径数有多少?
题解:
正常来说可以用结论:
但是这里直接用组合数会超范围,所以还是直接考虑用卡特兰数的模板
//#include<bits/stdc++.h>
#include<cstdio>
#include<cmath>
#define mp make_pair
#define se second
#define fi first
using namespace std;
typedef long long ll;
//typedef pair<int, int> pii;
//typedef pair<ll, int> pli;
//typedef pair<ll, ll> pll;
typedef long double ld;
const int N=1e6+10;
const int MAXN=20010;
const int INF=0x3f3f3f3f;
const double eps=0.0000001;
const ll mod=998244353;
ll n,m,x,y,z,k,cnt,t,len,q;
ll a[N],b[N],c[N];
ll h[36];
void init()
{
int i,j;
h[0]=h[1]=1;
for(i=2;i<36;i++)
{
h[i]=0;
for(j=0;j<i;j++)
h[i]=h[i]+h[j]*h[i-j-1];
}
}
int main()
{
cnt=0;
while(~scanf("%lld",&t))
{
cnt++;
if(t==-1) break;
init();
init(2*t);
printf("%lld %lld %lld %lld\n",cnt,t,h[t]*2);
}
}
D. Pawn
题意:
国际象棋棋盘最底行站了一个兵。 它只有两种行动方式: 向上左或向上右走。 它可以选择从最低行哪个节点开始他的旅程。 每个格子上有0-9颗豌豆,而士兵想移动到最上一行并且积累到尽可能多的豌豆。同时,因为这个士兵必须把豌豆平均分给自己和他的k个兄弟,他所收集到的豌豆必须是k+1的倍数。请找到他可以收集到的最多豌豆,并确定他的操作序列。
规定士兵不能手动扔出豌豆,并且他必须捡起所到达的每一个格子的所有豌豆。
题解:动态规划
d
p
[
i
]
[
j
]
[
k
]
dp[i][j][k]
dp[i][j][k]表示
i
i
i行
j
j
j列 数字和为
k
k
k的状态是否存在
一开始想用
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]来表示这一点处的数字和来转移,但同一个点会有很多数字和的情况,而且不确定那个是需要的,所以还需要再加一维。
#include<bits/stdc++.h>
#define mp make_pair
#define se second
#define fi first
using namespace std;
typedef long long ll;
//typedef pair<int, int> pii;
//typedef pair<ll, int> pli;
//typedef pair<ll, ll> pll;
typedef long double ld;
const int N=1e6+10;
const int MAXN=20010;
const int INF=0x3f3f3f3f;
const double eps=0.0000001;
const ll mod=998244353;
int n,m,x,y,z,k,cnt,t,len,q;
char a[200][200];
int maps[200][200];
int dp[200][200][1500];
char vis[N];
int main()
{
scanf("%d%d%d",&n,&m,&k);
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
{
scanf("%s",a[i]+1);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
maps[i][j]=a[i][j]-'0';
}
}
for(int i=1;i<=m;i++)
{
dp[n][i][maps[n][i]]=1;
}
for(int i=n-1;i>=1;i--)
{
for(int j=1;j<=m;j++)
{
int now=maps[i][j];
for(int p=now;p<=1100;p++)
{
int l=0,r=0;
if(j-1>=1) l=dp[i+1][j-1][p-now];
if(j+1<=m) r=dp[i+1][j+1][p-now];
dp[i][j][p]=max(l,r);
//if(dp[i][j][p]==1)
//printf("%d %d %d %d-%d\n",i,j,p,l,r);
}
}
}
int pos,ans=-1;
for(int j=1;j<=m;j++)
{
for(int l=0;l<=1100;l++)
{
if(dp[1][j][l]==1&&l%(k+1)==0)
{
if(l>ans)
{
ans=l;
pos=j;
}
}
}
}
cnt=0;
printf("%d\n",ans);
if(ans!=-1)
{
for(int i=2;i<=n;i++)
{
int now=maps[i-1][pos];
int pre=ans;
if(pos-1>=1&&dp[i][pos-1][pre-now]==1)
{
vis[++cnt]='R';
pos=pos-1;
ans=pre-now;
continue;
//如果左侧符合pos改变,下面的循环pos的意义就变了
}
if(pos+1<=m&&dp[i][pos+1][pre-now]==1)
{
vis[++cnt]='L';
pos=pos+1;
ans=pre-now;
}
}
printf("%d\n",pos);
for(int i=cnt;i>=1;i--)
printf("%c",vis[i]);
printf("\n");
}
}
C. Beautiful Lyrics
题意:
给定n个单词,每个单词由小写字母组成。每个单词至少包含一个元音。你将选择一些给定的单词,并尽可能多地写出优美的歌词。
每首抒情诗由两行组成。每一行由两个由空格分隔的单词组成。
歌词是美丽的,当且仅当它满足以下所有条件。
第一行第一个单词的元音个数与第二行第一个单词的元音个数相同。
第一行第二个单词的元音个数与第二行第二个单词的元音个数相同。
第一行的最后一个元音与第二行的最后一个元音相同。注意,元音后面可能有辅音。
题解:字符串模拟题
需要维护 一个单词中元音的个数和结尾元音
元音的个数相等单词的对数=
N
N
N,以相同元音结尾的单词的对数=
M
M
M
题目不难就是思路要想清楚,不然会很乱套,首先可以确定美丽歌词的数目。
美丽歌词的数目=
m
i
n
(
N
/
2
,
M
)
min(N/2,M)
min(N/2,M)。
确定了歌词数目后,由于M 可能会多,不可能会少,因为第二个单词,必须是相同元音结尾,多的就去补第一个单词。
所以先向
v
q
vq
vq中塞答案,然后往
v
p
vp
vp中塞答案
#include<bits/stdc++.h>
#define mp make_pair
#define se second
#define fi first
using namespace std;
typedef long long ll;
//typedef pair<int, int> pii;
//typedef pair<ll, int> pli;
//typedef pair<ll, ll> pll;
typedef long double ld;
const int N=1e6+10;
const int MAXN=20010;
const int INF=0x3f3f3f3f;
const double eps=0.0000001;
const ll mod=998244353;
int n,m,x,y,z,k,cnt,t,len,q;
string str[N];
vector<int>s[N][6];///s[i][j]储存 长度为i 结尾为j 的单词
int v[100];
vector<int> vp;///诗歌的第一句
vector<int> vq;///诗歌的第二句
vector<int> tmp[N];
int main()
{
cin>>n;
v['a'-'a']=1;
v['e'-'a']=2;
v['i'-'a']=3;
v['o'-'a']=4;
v['u'-'a']=5;
for(int i=0;i<n;i++)
{
cin>>str[i];
int sum=0;int pos=0;
for(int j=0;j<str[i].length();j++)
{
if(v[str[i][j]-'a'])
sum++,pos=v[str[i][j]-'a'];
}
if(sum>0)
s[sum][pos].push_back(i);
}
int num1=0,num2=0;
for(int i=1;i<N;i++)///计算有多少列
{
int sum=0;
for(int j=1;j<=5;j++)
{
sum+=s[i][j].size();
num2+=s[i][j].size()/2;
}
num1+=sum/2;
}
int ans=min(num1/2,num2);
cout<<ans<<endl;
k=ans;
for(int i=1;i<N;i++)
{
for(int j=1;j<=5;j++)
{
for(int p=0;p<s[i][j].size();p++)
{
if(p+1<s[i][j].size()&&k)
{
vq.push_back(s[i][j][p]);
p++;
vq.push_back(s[i][j][p]);
k--;
}
else
{
tmp[i].push_back(s[i][j][p]);
}
}
}
}
k=ans;
for(int i=1;i<N;i++)
{
for(int p=0;p<tmp[i].size();p++)
{
if(p+1<tmp[i].size()&&k)
{
vp.push_back(tmp[i][p]);
p++;
vp.push_back(tmp[i][p]);
k--;
}
}
}
for(int i=0;i<vp.size();i++){
cout<<str[vp[i]]<<" "<<str[vq[i]]<<endl;
}
}