2021.6.12模擬賽
阿新 • • 發佈:2021-06-12
題意
題解
1.一個P數如果是立方差數,不妨假設是x^3-y^3(x>y)。相當於(x-y)(x^2+xy+y^2),由於P是質數,因此x=y+1。又有(x-1)^2+x^2+x(x-1)=P,暴力列舉1~10^6判斷即可。2.令dp[i][ j]表示前i個數分成j段的最少價值。列舉這個斷點k,有dp[i][ j]=min{dp[k][ j-1]+sum(k+1,i)}。事實上這個k具有單調性,用經典的1D1D動態規劃優化即可。3.對於所有區間最小值為x的操作的區間交只有一種情況會出現矛盾:對於最小值超過x的區間的幷包含該區間交。因此我們可以二分答案,之後將所有最小值從大到小進行排序,利用並查集維護即可
2.令dp[i][ j]表示前i個數分成j段的最少價值。列舉這個斷點k,有dp[i][ j]=min{dp[k][ j-1]+sum(k+1,i)}。事實上這個k具有單調性,用經典的1D1D動態規劃優化即可。3.對於所有區間最小值為x的操作的區間交只有一種情況會出現矛盾:對於最小值超過x的區間的幷包含該區間交。因此我們可以二分答案,之後將所有最小值從大到小進行排序,利用並查集維護即可。
3.對於所有區間最小值為x的操作的區間交只有一種情況會出現矛盾:對於最小值超過x的區間的幷包含該區間交。因此我們可以二分答案,之後將所有最小值從大到小進行排序,利用並查集維護即可。
賽時程式碼
T1-cubicp立方數(60 ->100)
#include<bits/stdc++.h> using namespace std; #define ll long long const int N = 1e4+10; ll a[N],sum[N]; void init() { for(int i=1;i<=N;i++) a[i]=i*i*i; // for(int i=1;i<=N;i++) // sum[i]=a[i]-a[i-1]; } bool check() { ll p; scanf("%lld",&p); ll n=min((ll)(upper_bound(sum+1,sum+N+1,p)-sum),(ll)N); for(int i=1;i<=n;i++) for(int j=1;j<i;j++) if(a[i]-a[j]==p) return 1; return 0; } ll calc(ll x) { return 3*x*x+3*x+1; } bool judge() { ll p; scanf("%lld",&p); int l=1,r=1e6+10; while(l<r) { int mid=(l+r)>>1; if(calc(mid)<p) l=mid+1; else r=mid; } while(l<r) { int mid=(l+r)>>1; if(calc(mid)<=p) l=mid; else r=mid-1; } return calc(l)==p; } int main() { // freopen("cubicp.in","r",stdin); // freopen("cubicp.out","w",stdout); init(); int T; scanf("%d",&T); while(T--) { if(judge()) printf("YES\n"); else printf("NO\n"); } return 0; }
T2-dp動態規劃(40)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e3+10,INF = 0x3f3f3f3f;
int n,K;
int a[N];
ll dp[N][N][25];
ll sum[N][N];
ll jc(ll x){return x*(x-1)/2;}
ll calc(int l,int r)
{
ll ans=0;
for(int i = 1 ; i <= n ; i ++)
{
if(sum[r][i] != sum[l-1][i])
ans+=jc(sum[r][i]-sum[l-1][i]);
}
//printf("(%d,%d):%lld\n",l,r,ans);
return ans;
}
ll solve(int l,int r,int k)
{
// printf("checking[%d][%d][%d]\n",l,r,k);
if(dp[l][r][k]) return dp[l][r][k];
if(k == 1)
{ //printf(":dp[%d][%d][%d]=%lld\n",l,r,k,calc(l,r));
return dp[l][r][k]=calc(l,r);
}
dp[l][r][k]=INF;
for(int i=l;i<r;i++)
for(int j=1;j<k;j++)
{
if(i-l+1>=j&&r-i+1>=k-j)
dp[l][r][k]=min(dp[l][r][k],solve(l,i,j)+solve(i+1,r,k-j));
}
// printf("dp[%d][%d][%d]=%lld\n",l,r,k,dp[l][r][k]);
return dp[l][r][k];
}
int main()
{
//freopen("dp.in","r",stdin);
//freopen("dp.out","w",stdout);
scanf("%d%d",&n,&K);
bool flag=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(i>1&&a[i]!=a[i-1]) flag=1;
}
// if(!flag)
// {
// ll res=0;
// if(n%K==0)
// {
// res+=K*(jc(n/K));
// printf("%lld",res);
// }
// else
// {
// res+=(K-1)*(jc(n/K));
// res+=jc(n/K+n%K);
// printf("%lld",res);
// }
// return 0;
// }
for(int i=1;i<=n;i++)
{
sum[i][a[i]]=sum[i-1][a[i]]+1;
for(int j=1;j<=n;j++)
if(j!=a[i]) sum[i][j]=sum[i-1][j];
}
// for(int j = 1 ; j <= 2 ; j ++)
// for(int i = 1 ; i <= n ; i ++)
// printf("%d,%d:%lld\n",i,j,sum[i][j]);
printf("%lld",solve(1,n,K));
return 0;
}
/*
10 2
1 2 1 2 1 2 1 2 1 2
*/
T3-number遊戲(70)
#include<bits/stdc++.h>
using namespace std;
int read()
{
int a = 0,x = 1;char ch = getchar();
while(ch > '9' || ch < '0') {if(ch == '-') x = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') {a = a*10 + ch-'0';ch = getchar();}
return a*x;
}
const int N = 1005;
int l[N], r[N];
int main()
{
freopen("number.in", "r", stdin);
freopen("number.out", "w", stdout);
int n, k;
scanf("%d%d", &n, &k);
int ans;
for (ans=1;ans<=k;ans++)
{
int a,b,c;
a=read(),b=read(),c=read();
if (l[c]==0||r[c]==0)
l[c]=a, r[c]=b;
else
{
if (a>r[c]||b<l[c])
break;
if (a>l[c])
l[c]=a;
if (b<r[c])
r[c]=b;
}
for (int i=1;i<c;i++)
{
if (l[i]&&r[i]&&r[i]<=r[c]&&l[i]>=l[c])
{
printf("%d",ans);
return 0;
}
}
for (int i=c+1;i<=n;i++)
{
if (l[i]&&r[i]&&r[i]>=r[c]&&l[i]<=l[c])
{
printf("%d",ans);
return 0;
}
}
}
printf("%d", ans);
}
/*
20 5
1 10 4
1 5 4
5 6 6
6 10 6
4 5 5
*/