基础专题
1.hdu 1028 Ignatius and the Princess III 整数划分
1 #include<stdio.h> 2 __int64 dp[121][121]; 3 int main() 4 { 5 __int64 i,j,k,n,m; 6 for(i=0;i<=120;i++) 7 for(j=0;j<=120;j++) 8 dp[i][j]=0; 9 for(i=1;i<=120;i++) 10 { 11 dp[i][1]=1; 12 dp[1][i]=1; 13 } 14 for(i=1;i<=120;i++) 15 for(j=1;j<=120;j++) 16 { 17 if(i<j) 18 dp[i][j]=dp[i][i]; 19 else if(i>j) 20 dp[i][j]=dp[i-j][j]+dp[i][j-1]; 21 else if(i==j) 22 dp[i][j]=1+dp[i][j-1]; 23 } 24 while(scanf("%I64d",&n)>0) 25 { 26 printf("%I64d\n",dp[n][n]); 27 } 28 return 0; 29 }
2.hdu 1133 Buy the Ticket
这道题,以前没有用java的时候,还没有ac。
题意:有n个人手上有50元,m个人手上有100元。售票员手上没有零钱,所以必须要拥有50元的人先买。在任何时候,都要满足
50的人数>=100的人数才能满足题意要求。而且,每个人是不一样的,所以针对拥有50元 或者 100 的人又是有序的。
思路:dp[ i ] [ j ] 代表前 i 个人中,有 j 个50元的人已经买票了。
if( j > i - j ) dp[ i ] [ j ] = dp[ i -1] [j -1 ] + dp[i - 1] [ j ]; 讨论第i 个人是50元 还是 100元。
else dp[ i ] [ j ] = dp[ i-1 ] [ j-1 ];//此时只能由50元的人买票了.
由于有序,所以dp[n+m][n]*c[n]*c[m]; c[ ]代表阶乘.
//输入上要注意一下,m未必<=n,所以这样的情况,直接为0.
1 //package mywork; 2 3 import java.util.*; 4 import java.math.BigInteger; 5 import java.io.*; 6 7 public class Main { 8 9 static BigInteger c[] = new BigInteger[101]; 10 static BigInteger dp[][]= new BigInteger[202][202]; 11 12 public static void main(String[] args) { 13 // TODO Auto-generated method stub 14 fun(); 15 int t=1; 16 Scanner cin = new Scanner(System.in); 17 while(cin.hasNext()){ 18 int n = cin.nextInt(); 19 int m = cin.nextInt(); 20 if(n==0&&m==0)break; 21 if(m>n){ 22 System.out.println("Test #"+t+":"); 23 t++; 24 System.out.println("0"); 25 continue; 26 } 27 BigInteger hxl = dp[n+m][n].multiply(c[n]).multiply(c[m]); 28 System.out.println("Test #"+t+":"); 29 System.out.println(hxl); 30 t++; 31 } 32 } 33 static void fun(){ 34 c[0] = BigInteger.ONE; 35 for(int i=1;i<=100;i++) 36 c[i] = c[i-1].multiply(BigInteger.valueOf(i)); 37 38 for(int i=0;i<=200;i++){ 39 for(int j=0;j<=200;j++) 40 dp[i][j] = BigInteger.ZERO; 41 } 42 dp[1][1]=BigInteger.ONE; 43 for(int i=2;i<=200;i++){ 44 for(int j=1;j<=i;j++){ 45 if(j>i-j) 46 dp[i][j] = dp[i-1][j].add(dp[i-1][j-1]); 47 else dp[i][j] = dp[i-1][j]; 48 } 49 } 50 } 51 }
3.poj 3088 Push Botton Lock
1 // I want to say fuck! 2 题意: 给n个数字(1<=n<=11) ,从中选出 k 个元素,对于每一种情况,k个元素,求能分出几种集合。 3 一个元素只能在一个集合,一个集合中的元素是无序的,集合与集合之间是有序的。 4 这个是一种特殊的数转化过来的。 5 思路: n中选k个就有Cn1 Cn2 Cn3 .... Cnn这些情况。 6 对于每一种情况,求dp[i][j]代表,有i个元素,j个集合,则满足递推式 7 dp[i][j]=j*dp[i-1][j]+dp[i-1][j-1]; 8 当然,集合与集合直接是无序的,所以最后的时候,要乘 阶乘j.(集合的个数) 9 #include<stdio.h> 10 typedef __int64 LL; 11 12 LL dp[101][101]; 13 LL ans[13][13]; 14 LL nima[12]={1}; 15 16 void Init() 17 { 18 int i,j; 19 for(i=1;i<=11;i++) nima[i]=nima[i-1]*i; 20 for(i=0;i<=11;i++) ans[i][0]=1; 21 for(i=1;i<=11;i++) 22 { 23 for(j=1;j<=11;j++) 24 { 25 if(j==1) ans[i][1]=i; 26 else if(j==i) ans[i][i]=1; 27 else ans[i][j]=ans[i-1][j-1]+ans[i-1][j]; 28 } 29 } 30 dp[1][1]=1; 31 for(i=2;i<=100;i++) 32 for(j=1;j<=i;j++) 33 { 34 dp[i][j]=j*dp[i-1][j]+dp[i-1][j-1]; 35 } 36 } 37 int main() 38 { 39 int T,i,j,n,t; 40 LL sum,hxl; 41 Init(); 42 scanf("%d",&T); 43 for(t=1;t<=T;t++) 44 { 45 scanf("%d",&n); 46 sum=0; 47 for(i=1;i<=n;i++) 48 { 49 hxl=0; 50 for(j=1;j<=i;j++) 51 hxl=hxl+dp[i][j]*nima[j]; 52 sum=sum+hxl*ans[n][i]; 53 } 54 printf("%d %d %I64d\n",t,n,sum); 55 } 56 return 0; 57 }
4.poj 1496 Word Index
1 /*写得很糟 2 用了一个所谓的字符串哈希,发现以前神马都不管用。 3 ar 和 bc 都是同样的hash值。(⊙o⊙)…,不想改太多,就加了了 4 字符串判断了。 5 其实,由于长度<=5 而且 字母不会出现相同,用二进制哈希就很好了。 6 那么其他方法?? 7 */ 8 #include<iostream> 9 #include<stdio.h> 10 #include<cstring> 11 #include<string> 12 #include<cstdlib> 13 using namespace std; 14 15 struct node 16 { 17 int x; 18 int val; 19 char str[7]; 20 struct node *next; 21 }f[100007]; 22 void insert(int x,int num,char c[]) 23 { 24 int k=x%100007; 25 node *p; 26 p=f[k].next; 27 while(p!=NULL && (p->x!=x ||strcmp(p->str,c)!=0)) 28 { 29 p=p->next; 30 } 31 if(p==NULL) 32 { 33 p=(struct node*)malloc(sizeof(struct node)); 34 p->next=f[k].next; 35 f[k].next=p; 36 p->x=x; 37 strcpy(p->str,c); 38 p->val=num; 39 } 40 } 41 int found(int x,char c[]) 42 { 43 int k=x%100007; 44 node *p; 45 p=f[k].next; 46 while(p!=NULL && (p->x!=x || strcmp(p->str,c)!=0) ) 47 { 48 p=p->next; 49 } 50 if(p!=NULL) return p->val; 51 return 0; 52 } 53 unsigned int ELFHash(char *str) 54 { 55 unsigned int hash = 0; 56 unsigned int x = 0; 57 while (*str) 58 { 59 hash = (hash << 4) + (*str++); 60 if ((x = hash & 0xF0000000L) != 0) 61 { 62 hash ^= (x >> 24); 63 hash &= ~x; 64 } 65 } 66 return (hash & 0x7FFFFFFF); 67 } 68 void Init() 69 { 70 int i,j,s,t,k,tom=0,hxl; 71 for(i=0;i<100007;i++) 72 { 73 f[i].next=NULL; 74 f[i].val=f[i].x=0; 75 f[i].str[0]='\0'; 76 } 77 char A='a'-1; 78 char b[10]; 79 for(i=1;i<=26;i++) 80 { 81 b[0]=i+A; 82 b[1]='\0'; 83 hxl=ELFHash(b); 84 ++tom; 85 insert(hxl,tom,b); 86 }//one 87 for(i=1;i<=26;i++) 88 { 89 for(j=i+1;j<=26;j++) 90 { 91 b[0]=A+i; 92 b[1]=A+j; 93 b[2]='\0'; 94 hxl=ELFHash(b); 95 ++tom; 96 insert(hxl,tom,b); 97 } 98 }//two 99 for(i=1;i<=26;i++) 100 for(j=i+1;j<=26;j++) 101 for(k=j+1;k<=26;k++) 102 { 103 b[0]=A+i; 104 b[1]=A+j; 105 b[2]=A+k; 106 b[3]='\0'; 107 hxl=ELFHash(b); 108 ++tom; 109 insert(hxl,tom,b); 110 }//three 111 for(i=1;i<=26;i++) 112 { 113 for(j=i+1;j<=26;j++) 114 { 115 for(k=j+1;k<=26;k++) 116 { 117 for(s=k+1;s<=26;s++) 118 { 119 b[0]=i+A; 120 b[1]=j+A; 121 b[2]=k+A; 122 b[3]=s+A; 123 b[4]='\0'; 124 hxl=ELFHash(b); 125 ++tom; 126 insert(hxl,tom,b); 127 } 128 } 129 } 130 }//four 131 for(i=1;i<=26;i++) 132 { 133 for(j=i+1;j<=26;j++) 134 { 135 for(k=j+1;k<=26;k++) 136 { 137 for(s=k+1;s<=26;s++) 138 { 139 for(t=s+1;t<=26;t++) 140 { 141 b[0]=i+A; 142 b[1]=j+A; 143 b[2]=k+A; 144 b[3]=s+A; 145 b[4]=t+A; 146 b[5]='\0'; 147 hxl=ELFHash(b); 148 ++tom; 149 insert(hxl,tom,b); 150 } 151 } 152 } 153 } 154 }//five 155 156 } 157 int main() 158 { 159 Init(); 160 bool flag; 161 char a[10]; 162 int i,j,k; 163 while(scanf("%s",a)>0){ 164 k=strlen(a); 165 flag=false; 166 for(i=0;i<k;i++) 167 { 168 for(j=i+1;j<k;j++) 169 if(a[i]>=a[j])flag=true; 170 } 171 if(flag==true){ 172 printf("0\n"); 173 continue; 174 } 175 k=ELFHash(a); 176 k=found(k,a); 177 printf("%d\n",k); 178 } 179 return 0; 180 }
5.poj 1942 Paths on a Grid Cn+m n
1 #include<stdio.h> 2 typedef __int64 LL; 3 4 int main() 5 { 6 LL n,m,k,sum,i,j; 7 while(scanf("%I64d%I64d",&n,&m)>0) 8 { 9 if(n==0&&m==0)break; 10 k=n+m; 11 if(n>m) n=m; 12 sum=1; 13 for(i=1,j=k;i<=n;i++,j--) 14 sum=sum*j/i; 15 printf("%I64d\n",sum); 16 17 } 18 return 0; 19 }
6.fzu 2020 组合
1 #include<iostream> 2 #include<stdio.h> 3 #include<cstring> 4 #include<cstdlib> 5 using namespace std; 6 typedef long long LL; 7 8 LL pow_mod(LL a,LL b,LL p) 9 { 10 LL ans=1; 11 while(b) 12 { 13 if(b&1) ans=(ans*a)%p; 14 b=b>>1; 15 a=(a*a)%p; 16 } 17 return ans; 18 } 19 LL C(LL a,LL b,LL p){ 20 if(a<b) return 0; 21 if(b>a-b) b=a-b; 22 LL i,sum1=1,sum2=1; 23 for(i=0;i<b;i++){ 24 sum1=(sum1*(a-i))%p; 25 sum2=(sum2*(b-i))%p; 26 } 27 return (sum1*pow_mod(sum2,p-2,p))%p; 28 } 29 LL Lucas(LL n,LL m,LL p) 30 { 31 LL ans=1; 32 while(n&&m&&ans) 33 { 34 ans=(ans*C(n%p,m%p,p))%p; 35 n=n/p; 36 m=m/p; 37 } 38 return ans%p; 39 } 40 int main() 41 { 42 int T; 43 scanf("%d",&T); 44 while(T--){ 45 LL n,m,p; 46 scanf("%lld%lld%lld",&n,&m,&p); 47 if(p==1){ 48 printf("0\n"); 49 continue; 50 } 51 printf("%lld\n",Lucas(n,m,p)); 52 } 53 return 0; 54 }
1 /** 2 题意:C(n,m)%p; (1<=m<=n<=10^9 ,m<=10^4,m<p<10^9); 3 4 Lucas定理的运用。 5 Lucas(n,m,p)=C(n%p,m%p)%p*Lucas(n/p,m/p,p); p为素数. 6 7 { 8 纠正一个错误 9 for(i=1,j=n;i<=m;i++,j--) 10 sum=(sum*j/i)%p; 11 如果没有取模和溢出的条件下,这样做是可以的。 12 但是,取模就不对啦。例子C(10,4)%107。 13 } 14 后来知道,用了一个叫做乘法逆元的东东。 15 【定义】若整数a,b,p, 满足a·b≡1(mod p).则称a 为b 模p 的乘法逆元, 即a=b- 1mod p.其中, p 是模数。 16 乘法逆元有解的前提是gcd(b,p)=1;由于题意p为素数,那就肯定成立了. 17 应用到组合数中来就是: 18 a!/[b!*(a-b)!] % p == a! * [b!*(a-b)!]-1 %p 19 ??? 20 21 **/ 22 #include<iostream> 23 #include<stdio.h> 24 #include<cstring> 25 #include<cstdlib> 26 using namespace std; 27 typedef long long LL; 28 29 LL pow_mod(LL a,LL n,LL p) 30 { 31 LL ans=1; 32 while(n) 33 { 34 if(n&1) ans=(ans*a)%p; 35 n=n>>1; 36 a=(a*a)%p; 37 } 38 return ans; 39 } 40 void solve(LL n,LL m,LL p) 41 { 42 LL i,sum1=1,sum2=1; 43 for(i=0;i<m;i++) 44 { 45 sum1=(sum1*(n-i))%p; 46 sum2=(sum2*(m-i))%p; 47 } 48 LL ans=(sum1*pow_mod(sum2,p-2,p))%p; 49 printf("%lld\n",ans); 50 } 51 int main() 52 { 53 int T; 54 LL n,m,p; 55 scanf("%d",&T); 56 while(T--){ 57 scanf("%lld%lld%lld",&n,&m,&p); 58 n=n%p; 59 if(p==1){ 60 printf("0\n"); 61 continue; 62 } 63 solve(n,m,p); 64 } 65 return 0; 66 }