HDU 4945 2048
Q: I want to give you a bunch of numbers and ask how many subsets can be combined into 2048.
Ideas:
The number Spelling Rule is equivalent to multiplying a number by two. Therefore, if the number is not 2 ^ I, the number is not 2048. Therefore, these numbers are optional, that is, 2 ^ CNT.
After that, you only need to calculate the number of subsets that cannot spell out 2048, but the simple direct DP is 2048*100000 of the complexity, TLE
So we need to first enumerate the elements, then enumerate the number of such elements, then enumerate the 2048 states, and then use the combination to evaluate (the combination needs to reverse the element)
Why is it so fast? For example, when enumerating the element 2 ^ 5, the number of at most 2 ^ 6 enumeration elements is reduced.
Note: The question is relatively slow, so we can do less modulo operations.
Code:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef __int64 LL;#define mod 998244353#define N 2050#define M 100010int n,m,ans;int num[N],dp[15][N],two[M];LL f[M],g[M];inline void scan_d(int &ret){ char c; ret=0; while((c=getchar())<'0'||c>'9'); while(c>='0'&&c<='9') { ret=(ret<<3)+(ret<<1)+(c-'0'); c=getchar(); }}LL powmod(LL fm,int fn){ LL fans=1; while(fn) { if(fn&1) fans=(fans*fm)%mod; fn=fn>>1; fm=(fm*fm)%mod; } return fans;}int Min(int fa,int fb){ if(fa<fb) return fa; return fb;}int main(){ int cas=1,i,j,k,kk,s,amt; two[0]=1; f[0]=1; for(i=1;i<M;i++) { two[i]=(two[i-1]<<1)%mod; f[i]=f[i-1]*i%mod; } g[0]=1; g[100000]=powmod(f[100000],mod-2); for(i=99999;i>=1;i--) g[i]=g[i+1]*(i+1)%mod; for(;;) { scan_d(n); if(!n) break; for(i=0;i<=11;i++) { num[two[i]]=0; for(j=0;j<2048;j++) dp[i][j]=0; } dp[0][0]=1; ans=0; for(i=1;i<=n;i++) { scan_d(k); num[k]++; } m=num[two[11]]; for(i=0;i<11;i++) { amt=num[two[i]]; m+=amt; s=Min(two[11-i],amt); for(j=0;j<=s;j++) { LL x=f[amt]*g[amt-j]%mod*g[j]%mod; for(k=(j<<i),kk=0;k<2048;k++,kk++) if(dp[i][kk]) { dp[i+1][k]+=dp[i][kk]*x%mod; if(dp[i+1][k]>=mod) dp[i+1][k]-=mod; } } } for(i=0;i<2048;i++) { ans+=dp[11][i]; if(ans>=mod) ans-=mod; } ans=(LL)(two[m]-ans+mod)%mod*two[n-m]%mod; printf("Case #%d: %d\n",cas++,ans); } return 0;}
HDU 4946 area of mushroom
Q: On the plane, there are many people. If the distance from this person to a certain position is strictly smaller than that of others, this position belongs to this person. The range of a few people is infinite.
Ideas:
First, only the people with the highest speed may have an infinite number. People with a lower speed will always be caught up by people with the highest speed.
Secondly, only the talents on the convex bag may be infinite. This limit can prove that the points on the Infinite Distant convex bag will definitely exceed the convex packet interior point.
The person with the final coincidence position and the highest speed must have nothing
Note: The vertices on the sides ignored by the convex hull calculated by the General convex hull template must be specific to the vertices on the edge.
# Include <cstdio> # include <cstring> # include <cmath> # include <iostream> # include <algorithm> using namespace STD; double EPS = 1e-8; double Pi = ACOs (double) (-1); inline int DCMP (double A) // judge a double-type symbol {If (FABS (a) <EPS) return 0; if (a> 0) return 1; else return-1;} struct point {Double X, Y, V; int ID, mark; inline point (double _ x = 0.0, double _ y = 0.0) {x = _ x; y = _ y;} inline point operator-(con St point & B) const {return point (X-B. x, Y-B. y);} inline point operator + (const point & B) const {return point (x + B. x, Y + B. y);} inline point operator | (const double & B) const {return point (x * B, y * B);} inline double operator ^ (const point & B) const {return x * B. y-y * B. x;} inline double operator * (const point & B) const {return x * B. X + Y * B. y;} inline void input () {scanf ("% Lf % lf ", & X, & Y, & V); Mark = 0 ;}}; inline bool operator == (const point & A, const point & B) {return DCMP (. x-B. x) = 0 & DCMP (. y-B. y) = 0;} inline double Len (point a) // vector touch {return SQRT (A * A);} inline double angle (point a, point B) // The angle between the two starting points! {Double ans = ACOs (A * B)/Len (a)/Len (B); Return ans;} inline double jijiao (point v) {return atan2 (v. y, V. x);} inline point rote (point a, double rad) // rotate the rad radian counterclockwise !! {Return point (. x * Cos (RAD)-. y * sin (RAD),. x * sin (RAD) +. y * Cos (RAD);} inline int isinteger (double XX) // determines whether a double number is an integer !! {Return DCMP (XX-int (xx + 0.05) = 0;} inline double torad (double deg) // converts degrees to radians {return deg/180 * PI ;} inline double DIS (point a, point B) // the distance between two points {return SQRT (a-B) * (a-B ));} inline point getjiaodian (point P, point V, point Q, point W) // There is a unique intersection on the premise !! The parameter equations V and W are the direction vectors, p and q, which are the points on two straight lines! {Point U; u = p-Q; Double T = (w ^ U)/(V ^ W); V. X = T * v. x; V. y = T * v. y; return P + V;} inline double diantoline (point P, point A, point B) // distance from a point to a straight line {point V1 = B-, v2 = P-A; return FABS (V1 ^ V2)/Len (V1); // do not take the absolute value as directed !!} Inline int isxiangjiao (point a, point B, point C, point D) // determines the intersection of a straight line, coincidence, parallel !!! {Point aa, BB, CC, DD; AA = B-A; BB = D-C; If (DCMP (AA ^ bb )! = 0) return 1; // intersection else {AA = a-d; BB = B-c; CC = a-c; dd = B-d; if (DCMP (AA ^ bb )! = 0 | DCMP (CC ^ dd )! = 0) return 2; // parallel else return 3; // coincidence }}//********************************* **************** // find a convex bag !!! Inline bool operator <(const point & A, const point & B) {return DCMP (. x-B.x) <0 | (DCMP (. x-B.x) = 0 & DCMP (. y-B.y) <0);} inline bool mult (point B, point C, point A) {return DCMP (B. x-a.x) * (C. y-a.y)-(B. y-a.y) * (C. x-a.x)> = 0;} inline int Graham (point PNT [], int N, point res []) {int I, Len, K = 0, Top = 1; sort (PNT, PNT + n); If (n = 0) return 0; Res [0] = PNT [0]; If (n = 1) return 1; res [1] = PNT [1]; If (n = = 2) return 2; Res [2] = PNT [2]; for (I = 2; I <n; I ++) {While (top & mult (PNT [I], Res [Top], Res [Top-1]) Top --; res [++ top] = PNT [I];} Len = top; Res [++ top] = PNT [n-2]; for (I = N-3; i> = 0; I --) {While (top! = Len & mult (PNT [I], Res [Top], Res [Top-1]) Top --; Res [++ top] = PNT [I];} return top ;} //************************************** * *********** point list [5000]; // Input Point, subscript starts from 0 !! Point dd [5000]; // the point on the output convex hull. The subscript starts from 0 !! Point f [5000]; int ans [5000]; int main () {int T, I, j; int N; int CA = 0; while (~ Scanf ("% d", & N) {If (! N) break; CA ++; memset (ANS, 0, sizeof (ANS); double MAV = 0; for (I = 0; I <n; I ++) {list [I]. input (); list [I]. id = I; MAV = max (MAV, list [I]. v);} If (DCMP (MAV) = 0) {printf ("case # % d:", CA); for (I = 0; I <N; I ++) printf ("% d", ANS [I]); printf ("\ n"); continue;} int CNT = 0; for (I = 0; I <n; I ++) {If (DCMP (list [I]. v-MAV) = 0) f [CNT ++] = list [I];} Sort (F, F + CNT); for (I = 0; I <cnt-1; I ++) {If (F [I] = f [I + 1]) {f [I]. mark = 1; F [I + 1]. mark = 1 ;}} Int Top = Graham (F, CNT, DD); dd [Top] = dd [0]; for (j = 0; j <CNT; j ++) {If (! F [J]. mark) for (I = 0; I <top; I ++) {double AA = Len (F [J]-dd [I]); double BB = Len (F [J]-dd [I + 1]); double CC = Len (Dd [I + 1]-dd [I]); if (DCMP (CC-aa-bb) = 0) {ans [f [J]. id] = 1; break ;}}printf ("case # % d:", CA); for (I = 0; I <n; I ++) printf ("% d", ANS [I]); printf ("\ n");} return 0 ;}
HDU 4948 kingdom
In the figure, there is only one unidirectional edge between any two points to find a sequence of vertices, so that the distance between the other points to the vertex cannot exceed 2 at each new vertex.
Ideas:
In the opposite way, if the distance is not greater than 2 after the point is subtracted from the source image, the maximum point of the input is subtracted each time. This proves that the solution is more detailed. if the distance from a point set to U is W and 2 is Y, if the distance between V and U is greater than 2, then the V is not directly directed to W, So w must be connected to V and U there must be a conflict between V and U.
Code:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 510int n;int ans[N],in[N];char maz[N][N];inline void scan_d(int &ret){ char c; ret=0; while((c=getchar())<'0'||c>'9'); while(c>='0'&&c<='9') { ret=(ret<<3)+(ret<<1)+(c-'0'); c=getchar(); }}int main(){ int i,j,k,p; for(;;) { scan_d(n); if(!n) break; for(i=1;i<=n;i++) in[i]=0; for(i=1;i<=n;i++) { scanf("%s",maz[i]+1); for(j=1;j<=n;j++) { if(maz[i][j]=='1') in[j]++; } } for(i=1;i<=n;i++) { k=-1; for(j=1;j<=n;j++) { if(in[j]>k) { k=in[j]; p=j; } } in[p]=-1; ans[i]=p; for(j=1;j<=n;j++) { if(in[j]>0&&maz[p][j]=='1') in[j]--; } } for(i=n;i;i--) printf("%d%s",ans[i],(i!=1)?" ":"\n"); } return 0;}
HDU 4950
Question: omitted
Ideas:
Determine if you can kill K or kill k + 1 or kill blood.
Code:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef __int64 LL;LL h,a,b,k;int main(){ int t=1; for(;;) { scanf("%I64d%I64d%I64d%I64d",&h,&a,&b,&k); if(!h&&!a&&!b&&!k) break; printf("Case #%d: ",t++); if(h<=a) puts("YES"); else if(a*k-b*(k-1)>=h) puts("YES"); else if(a*k>b*(k+1)) puts("YES"); else puts("NO"); } return 0;}
HDU 4951 multiplication table
Here is a P-base multiplication table. Now he replaces all the numbers, for example, 0, 1, 3, and 8... Ask you about the new table 0, 1, 2... What are the numbers...
Ideas:
0 can be used to identify a row, a column, all the same, and 1 can also be used to determine that ten digits are all numbers converted from 0.
Other numbers are determined based on ten digits. In P-based conditions, for example, 3 * X, the number of digits must be only three.
Code:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 510int a[N][N][2],ans[N],vis[N];int n;inline void scan_d(int &ret){ char c; ret=0; while((c=getchar())<'0'||c>'9'); while(c>='0'&&c<='9') { ret=(ret<<3)+(ret<<1)+(c-'0'); c=getchar(); }}int main(){ int t=1,i,j,k,one,zero; for(;;) { scanf("%d",&n); if(!n) break; for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { scan_d(a[i][j][0]); scan_d(a[i][j][1]); } } for(i=1;i<=n;i++) { for(j=1;j<=n;j++) vis[a[i][j][0]]=1; for(j=0,k=0;j<n;j++) { k+=vis[j]; vis[j]=0; } if(k!=1) ans[k]=i; else { for(j=1;j<=n;j++) if(a[i][j][0]!=a[i][j][1]) break; if(j<=n) { ans[1]=i; one=i; } else { ans[0]=i; zero=a[i][1][0]; } } } printf("Case #%d: %d",t++,zero); for(i=1;i<n;i++) printf(" %d",a[ans[i]][one][1]); printf("\n"); } return 0;}
HDU 4952 number Transformation
Question: Give You A n k, a total of K operations. The I operation converts n to a multiple of I, which is greater than or equal to the minimum value of N.
Ideas:
Each N can be split into x * I, so x' (I + 1)> = xi, then x'> = x-x/(I + 1) we found that x' is decreasing, so there is always an end. Therefore, the brute force maintenance x' is followed by K.
Code:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;__int64 x,y;int main(){ int t=1,i; for(;;) { scanf("%I64d%I64d",&x,&y); if(!x&&!y) break; for(i=1;i<y;i++) { if(x<i+1) break; x-=x/(i+1); } printf("Case #%d: %I64d\n",t++,x*y); } return 0;}