17-09-15模拟赛

T1:可以发现a*b=k3,k表示所有不同轮的道具各取一个相乘后的值。

二分枚举3√(a*b),如能找到输出"YES",否则输出"NO".注意特判乘积为0的情况。

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define ll long long
 5 using namespace std;
 6 inline ll in(){
 7     ll x=0;bool f=0; char c;
 8     for (;(c=getchar())<'0'||c>'9';f=c=='-');
 9     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
10     return f?-x:x;
11 }
12 ll pd,ans,res,a,b;
13 int n;
14 inline ll bis(ll x){
15     if (x==1ll) return 1ll;
16     ll l=1ll,r=min(x,1000001ll);
17     while (l<=r){
18         ll mid=(l+r)>>1;
19         if (1ll*mid*mid*mid<=x) ans=mid,l=mid+1;
20         else r=mid-1;
21     }return (1ll*ans*ans*ans==x)?ans:-1;
22 }
23 int main()
24 {
25     scanf("%d",&n);for (int i=1;i<=n;++i){
26         a=in();b=in();if (!(a*b)){printf(a==b?"YES\n":"NO\n");continue;}
27         pd=a*b;ans=0ll;res=bis(pd);
28         printf(((res==-1)||(a%res)||(b%res))?"NO\n":"YES\n");
29     }return 0;
30 }

T2:动态规划。令f[i][j]表示取i个数且这些数的乘积有j个因数5时乘积中因数2的个数。

则f[i][j]=max{f[i-1][j-v5[k]]+v2[k]},其中v2[i]与v5[i]因数2与因数5的个数。时间复杂度O(nk∑log5ai).

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define MN 202
 5 #define Lg 26
 6 #define ll long long
 7 using namespace std;
 8 inline ll in(){
 9     ll x=0;bool f=0; char c;
10     for (;(c=getchar())<'0'||c>'9';f=c=='-');
11     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
12     return f?-x:x;
13 }
14 ll x,t;
15 int f[MN][MN*Lg],b2,b5,n,k,cnt,sum,ans=0;
16 int main()
17 {
18     scanf("%d%d",&n,&k);ans=sum=0;
19     memset(f,200,sizeof(f));f[0][0]=0;
20     for (int i=1;i<=n;++i){
21         x=in();b2=b5=0;
22         if (!x) {ans=1;continue;} t=x;
23         while (!(t&1)) {++b2;t>>=1;}
24         while (!(t%5)) {++b5;t/=5;}sum+=b5;
25         for (int j=min(k,i);j>=0;--j)
26         for (int k=0;k<=sum;++k)f[j+1][k+b5]=max(f[j+1][k+b5],f[j][k]+b2);
27     }
28     for (int i=0;i<=sum;++i) ans=max(ans,min(i,f[k][i]));
29     printf("%d",ans);return 0;
30 }

T3:考虑将盘子的左端点与右端点从小到大排序。

从小到大扫描右端点,则该点的答案为与其对应的左端点的相对位置(离散化求得)开始的最长不降子序列。

该操作可以使用线段树维护区间最大值完成。答案即为全局最大值。

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define MN 100005
 5 using namespace std;
 6 inline int in(){
 7     int x=0;bool f=0; char c;
 8     for (;(c=getchar())<'0'||c>'9';f=c=='-');
 9     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
10     return f?-x:x;
11 }
12 struct pla{
13     int l,r;
14 }p[MN];
15 int mx[(1<<19)],a[MN],n,rd,x,cnt,M;
16 inline bool cmp(pla a,pla b){return a.r==b.r?a.l>b.l:a.r<b.r;}
17 inline void add(int x,int k){
18     for (x+=M;x;x>>=1) mx[x]=max(mx[x],k);
19 }
20 inline int query(int l,int r){
21     int res=0;
22     for (l+=M-1,r+=M+1;l^r^1;l>>=1,r>>=1){
23         if (~l&1) res=max(res,mx[l^1]);
24         if ( r&1) res=max(res,mx[r^1]);
25     }return res;
26 }
27 int main()
28 {
29     n=in();for (int i=1;i<=n;++i){
30         rd=in();x=in();a[i]=p[i].l=x-rd;p[i].r=x+rd;
31     }sort(a+1,a+n+1);cnt=unique(a+1,a+n+1)-a-1;
32     sort(p+1,p+n+1,cmp);for (M=1;M<n+2;M<<=1);
33     for (int i=1;i<=n;++i){
34         p[i].l=lower_bound(a+1,a+cnt+1,p[i].l)-a;
35         add(p[i].l,query(p[i].l,cnt)+1);
36     }printf("%d",mx[1]);return 0;
37 }

 

posted on 2017-09-19 13:48  whz2002  阅读(120)  评论(0编辑  收藏  举报