题目:A. LCM Problem
题意:给定l和r,找到一对x,y,LCM(x,y)属于[l,r]。
设gcd,最小的x为l,可知最优的y为2*l。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=1e9+7;
const int MAXlen=2e4+10;
const int MAX=2e5+10;
double eps=1e-4;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int l,r;
scanf("%d %d",&l,&r);
if(2*l>r)
{
printf("-1 -1\n");
continue;
}
printf("%d %d\n",l,2*l);
}
return 0;
}
题目:B. Array Walk
题意:给定n,k,z,长度为n的数组,k为你移动的总次数,z是你向左移动的次数。每次你可以选择向左还是向右移动,从a[i]到a[i-1],总价值+a[i-1]同理向右移动。在一个点不能连续向左移动2次及两次以上。问价值最大的。
每次自己写的dp状态定的偏点转移方程就很麻烦,还是需要改进。
z的值不大可以作为dp状态量,dp[i][j]:在第i个变量已经向左移动了j次的最大价值。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=1e9+7;
const int MAXlen=2e4+10;
const int MAX=2e5+10;
double eps=1e-4;
ll a[100010];
ll dp[100010][10];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ll n,k,z;
ll i,j;
scanf("%lld %lld %lld",&n,&k,&z);
for(i=1;i<=n;i++)
{
for(j=0;j<7;j++)
dp[i][j]=0;
scanf("%lld",&a[i]);
}
ll ans=0;
dp[1][0]=a[1];
for(i=2;i<=n;i++)
{
for(j=0;j<=z;j++)
{
dp[i][j]=max(dp[i-1][j]+a[i],dp[i][j]);//没有向左移动
if(i-1+2*j<=k)
ans=max(ans,dp[i][j]);
dp[i-1][j+1]=max(dp[i-1][j+1],dp[i][j]+a[i-1]);//向左移动
if(i-2+2*(j+1)<=k&&(j+1<=z))//确保在k次之内,向左移动次数不大于z
ans=max(ans,dp[i-1][j+1]);
}
}
printf("%lld\n",ans);
}
return 0;
}
题目:C. Good String
题意:
初始:1 2 3 4 5 6->2 3 4 5 6 1要等于6 1 2 3 4 5
2=6=4,1=3=5。奇数时全部相等。
只有这两种情况。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=1e9+7;
const int MAXlen=2e4+10;
const int MAX=2e5+10;
double eps=1e-4;
char s[200010];
int book[12];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(book,0,sizeof(book));
scanf("%s",s);
int n,i,j;
n=strlen(s);
int ans=n-2;
for(i=0;i<n;i++)
book[s[i]-'0']++;
for(i=0;i<=9;i++)
ans=min(ans,n-book[i]);
for(i=0;i<=9;i++)
{
if(!book[i])
continue;
for(j=0;j<=9;j++)
{
if(!book[j]||i==j)
continue;
bool gg=true;
int sum=0;
for(int k=0;k<n;k++)
{
if(gg){
if(s[k]-'0'==i)
{
gg=false;
sum++;
}
}
else{
if(s[k]-'0'==j)
{
gg=true;
sum++;
}
}
}
if(sum&1)
sum--;
ans=min(ans,n-sum);
}
}
printf("%d\n",ans);
}
return 0;
}
题目:D. Segment Intersections
题意:初始化有两个区间[l1,r1],[l2,r2],有n个这两个区间,每次你可以给第i个区间左端点-1,或者右端点+1,如果两个区间的重叠部分时[x,y]则价值为y-x。最小操作几次使得价值为k。
可以确定,先尽量把第i个区间相互完善到,max(r2,r1)-min(l1,l2),再去判断一下完成后,补充2个操作换一个的价值记录下来。之后就是分情况讨论,两个区间开始就没有重叠部分的价值,以及完全重合,部分重合的情况,我写的过于繁杂可以忽略。代码丑的一
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=1e9+7;
const int MAXlen=2e4+10;
const int MAX=2e5+10;
double eps=1e-4;
ll dp[200100];
int main()
{
int T;
scanf("%d",&T);
while(T--){
ll n,i,j,k;
scanf("%lld %lld",&n,&k);
for(i=0;i<=n;i++)
dp[i]=llinf;
ll l1,r1,l2,r2;
ll ans=0;
scanf("%lld %lld",&l1,&r1);
scanf("%lld %lld",&l2,&r2);
if(l1>l2){
swap(l1,l2);
swap(r1,r2);
}
if(r1<=l2){
ll sum=0;
ll rmax=r2-l1,rcha=l2-r1;
for(i=1;i<=n;i++){
if(sum+rmax<=k){
sum+=rmax;
ans+=rcha+rmax;
if(k-sum>=0)
dp[i]=ans+2*(k-sum);
}
else{
ans+=rcha+(k-sum);
sum=k;
break;
}
}
if(sum<k){
ans+=(k-sum)*2;
}
for(i=1;i<=n;i++)
ans=min(ans,dp[i]);
printf("%lld\n",ans);
}
else if(r2>r1){
ll sum=(r1-l2)*n;
ll rmax=l2-l1+r2-r1;
if(sum>=k)
{
printf("0\n");
continue;
}
for(i=1;i<=n;i++)
{
if(sum+rmax<=k)
{
ans+=rmax;
sum+=rmax;
if(k-sum>=0)
dp[i]=ans+(k-sum)*2;
}
else{
ans+=(k-sum);
sum=k;
break;
}
}
if(sum<k){
ans+=(k-sum)*2;
}
for(i=1;i<=n;i++)
ans=min(ans,dp[i]);
printf("%lld\n",ans);
}
else {
ll rmax=l2-l1+r1-r2;
ll sum=(r2-l2)*n;
if(sum>=k)
{
printf("0\n");
continue;
}
for(i=1;i<=n;i++){
if(sum+rmax<=k)
{
sum+=rmax;
ans+=rmax;
if(k-sum>=0)
dp[i]=ans+(k-sum)*2;
}
else
{
ans+=(k-sum);
sum=k;
break;
}
}
if(sum<k){
ans+=(k-sum)*2;
}
for(i=1;i<=n;i++)
ans=min(ans,dp[i]);
printf("%lld\n",ans);
}
}
return 0;
}
题目:E. Calendar Ambiguity
题意:给定一年m个月,一个月d天,一周w天,问x月y日的星期等于y月x日的星期的一对(x,y)的对数。
计算日期星期是:
(
(
x
−
1
)
∗
d
+
y
)
m
o
d
w
+
1
=
(
(
y
−
1
)
∗
d
+
x
)
m
o
d
w
+
1
((x-1)*d+y) \mod w+1 = ((y-1)*d+x)\mod w+1
((x−1)∗d+y)modw+1=((y−1)∗d+x)modw+1
得到
(
y
−
x
)
∗
(
d
−
1
)
=
k
∗
w
,
k
>
=
1
且
是
整
数
(y-x)*(d-1) = k*w,k>=1且是整数
(y−x)∗(d−1)=k∗w,k>=1且是整数
y,x属于min(d,m),如果日期大,就没有这个月份。
y>x,x=1时y-x为[1,m-1],但是我们还需要判断(d-1)与w是否存在倍数关系,所以继续gcd(d-1,w)同除,(d-1)与w互质,只需要考虑(y-x)与w的关系了,w=/gcd,(d-1)=/gcd,值就是
m
−
1
w
\frac{m-1}{w}
wm−1。同理x=2,3…。
∑
i
=
w
m
−
1
i
w
\sum_{i=w}^{m-1} \frac{i}{w}
∑i=wm−1wi
随意带一个值观察可发现规律。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=1e9+7;
const int MAXlen=2e4+10;
const int MAX=2e5+10;
double eps=1e-4;
ll dp[200100];
ll gcd(ll a,ll b)
{
if(!b)
return a ;
else{
return gcd(b,a%b);
}
}
int main()
{
for(int i=1;i<=14;i++)
{
// printf("%d ",i/5);
}
int T;
scanf("%d",&T);
while(T--){
ll m,d,w;
scanf("%lld %lld %lld",&m,&d,&w);
ll g=gcd(d-1,w);
w/=g;
m=min(m,d)-1;
ll n=(m/w)-1;
ll ans=n*(n+1)/2*w;
ans+=(m%w+1)*(m/w);
printf("%lld\n",ans);
}
return 0;
}