一直不大喜欢写题解 尤其做的很纠结的题目 终于纠结完了 就想代码一贴完事。缺点一:理解不透彻;二:很容易忘;三:不利于以后回顾复习;四:写代码容易乱;
以这个专题为开始吧 把一些题目总结一下 解释一下 同一类型的放在一块 。
hdu1465 不容易系列之一 (错排公式)
虽说大家知道 还是把这个小小说一下
来自百度百科
1 #include <iostream> 2 #include<cstdio> 3 #include<stdlib.h> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #include<vector> 8 #include<queue> 9 #include<stack> 10 #include<set> 11 using namespace std; 12 #define LL long long 13 LL f[22]; 14 int main() 15 { 16 int i,n; 17 f[1] = 0; 18 f[2] = 1; 19 while(cin>>n) 20 { 21 for(i = 3; i <= n ; i++) 22 f[i] = (i-1)*(f[i-1]+f[i-2]); 23 cout<<f[n]<<endl; 24 } 25 return 0; 26 }
poj1850 Code
以前做过 没印象了。。
仔细想一下 也是很简单的 一个字母的所有排列就是C(n,1),二个字母C(n,2),三个字母C(n,3)........依次
具体的就类似于逐位了 注意下细节就OK了
1 #include <iostream> 2 #include<cstdio> 3 #include<stdlib.h> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #include<vector> 8 #include<queue> 9 #include<stack> 10 #include<set> 11 using namespace std; 12 #define LL long long 13 char s[12]; 14 LL c[30][15]; 15 void init() 16 { 17 int i,j; 18 for(i = 0 ;i <= 26 ;i++) 19 c[i][0] = 1; 20 for(i = 1 ; i <= 26 ;i++) 21 for(j = 1 ; j <= 10 ; j++) 22 c[i][j] = c[i-1][j-1]+c[i-1][j]; 23 } 24 int main() 25 { 26 int i,j,k; 27 init(); 28 while(cin>>s) 29 { 30 k = strlen(s); 31 if(k>1) 32 { 33 for(i = 0 ; i < k-1 ; i++) 34 if(s[i+1]<s[i]) break; 35 if(i!=k-1) {puts("0");continue;} 36 } 37 LL ans=0; 38 for(i = 1 ; i < k ;i++) 39 ans+=c[26][i]; 40 int t; 41 for(i = 0; i < k ;i++) 42 { 43 if(i!=0) 44 t = 'z'-s[i-1]-1; 45 else 46 t = 25; 47 //cout<<'z'-s[i]+1<<endl; 48 for(j = max(('z'-s[i]+1),k-i-1) ; j <= t ; j++) 49 { 50 //cout<<j<<endl; 51 ans+=c[j][k-i-1]; 52 } 53 } 54 ans++; 55 cout<<ans<<endl; 56 } 57 return 0; 58 }
poj2773 Happy 2006 二分+容斥原理
容斥原理可以明显的看的出 也算是模板题了
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 using namespace std; 11 #define N 10000000000 12 #define LL long long 13 int p[32],g; 14 LL sum=0; 15 int gcd(int a,int b) 16 { 17 return b==0?a:gcd(b,a%b); 18 } 19 void dfs(int num,LL y,int i,LL n) 20 { 21 y = p[i]*y; 22 if(num%2==0) sum-=n/y; 23 else sum+=n/y; 24 for(int j = i+1 ; j <= g ; j++) 25 dfs(num+1,y,j,n); 26 } 27 int main() 28 { 29 int m,k,i; 30 while(cin>>m>>k) 31 { 32 g = 0; 33 for(i = 2; i <= m ;i++) 34 { 35 if(m%i==0) p[++g] = i; 36 while(m%i==0) 37 { 38 m/=i; 39 } 40 } 41 if(m!=1) p[++g] = m; 42 LL low = 1,high = N,mid; 43 LL ans; 44 while(low<=high) 45 { 46 mid = (low+high)/2; 47 sum=0; 48 for(i = 1; i <= g; i++) 49 { 50 dfs(1,1,i,mid); 51 } 52 /*if(mid-sum==k) 53 { 54 while(gcd(mid,k)!=1)mid--; 55 break; 56 }*/ 57 if(mid-sum<k) low = mid+1; 58 else {high = mid-1;} 59 } 60 cout<<low<<endl; 61 } 62 return 0; 63 }
这跳骚很牛X 。。特别能跳
这个可以想到 可以跳出相差为一的 就是gcd(x1,x2,,....xn) = 1,具体我也不知道怎么证 我是以欧几里得猜的 ax+by = gcd(x,y) 有解
这个题求补集 把每一次的减去
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL __int64 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int p[32]; 18 double ppow(int x,int n) 19 { 20 int i; 21 double s = 1; 22 for(i = 1; i <= n ;i++) 23 s*=x; 24 return s; 25 } 26 int main() 27 { 28 int i,j,n,m; 29 scanf("%d%d",&n,&m); 30 int g = 0; 31 int q = m; 32 for(i = 2 ; i*i <= m ;i++) 33 { 34 if(m%i==0) p[++g] = i; 35 while(m%i==0) 36 m/=i; 37 if(i>m) break; 38 } 39 if(m!=1) p[++g] = m; 40 double s = ppow(q*1.0,n); 41 for(i = 1 ; i < (1<<g) ; i++) 42 { 43 int o = 0,y=1; 44 for(j = 0 ; j < g ; j++) 45 { 46 if(i&(1<<j)) 47 { 48 o++; 49 y*=p[j+1]; 50 } 51 } 52 LL x = q/y; 53 if(o%2) s-=ppow(x,n); 54 else s+=ppow(x,n); 55 } 56 printf("%I64d ",(LL)s); 57 return 0; 58 }
这个其实把最大公约数除去之后 求一下互质的个数 可能数据有点水吧 直接枚举每一个的与其互质的个数 然后加起来
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 #define LL __int64 10 #define N 100010 11 LL o[N]; 12 int p[22]; 13 LL init(int s1,int s2) 14 { 15 int i,j,e; 16 LL cnt = 0; 17 for(i = s1 ; i >= 2 ; i--) 18 { 19 int g = 0,x=i; 20 for(j = 2 ; j*j <= x ; j++) 21 { 22 if(x%j==0){p[++g] = j;} 23 while(x%j==0) x/=j; 24 } 25 if(x!=1) p[++g] = x; 26 int ans = i+s2-s1; 27 for(j = 1 ; j < (1<<g) ; j++) 28 { 29 int s = 0,y=1; 30 for(e = 0 ; e < g ; e++) 31 { 32 if(j&(1<<e)) 33 { 34 s++; 35 y*=p[e+1]; 36 } 37 } 38 if(s%2) 39 { 40 ans-=i/y; ans-=(s2/y-s1/y); 41 } 42 else {ans+=i/y;ans+=(s2/y-s1/y); 43 } 44 } 45 cnt += ans; 46 } 47 return cnt+s2-s1+1; 48 } 49 int main() 50 { 51 int k,a,b,c,d; 52 int t,kk=0; 53 cin>>t; 54 while(t--) 55 { 56 scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); 57 if(b>d) swap(b,d); 58 printf("Case %d: ",++kk); 59 if(k==0||b<k) 60 { 61 cout<<"0 "; 62 continue; 63 } 64 cout<<init(b/k,d/k)<<endl; 65 } 66 return 0; 67 }
直接套模板
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdio> 5 #include<stdlib.h> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 int k[10],o[10],num[10]; 10 int c1[55],c2[55]; 11 bool f[10]; 12 int main() 13 { 14 int i,j,a,b,n,k,t,e; 15 cin>>t; 16 while(t--) 17 { 18 memset(o,0,sizeof(o)); 19 memset(f,0,sizeof(f)); 20 memset(c1,0,sizeof(c1)); 21 memset(c2,0,sizeof(c2)); 22 cin>>n>>k; 23 int g = 0; 24 for(i = 1; i <= k ;i++) 25 { 26 cin>>a>>b; 27 o[a]+=b; 28 if(!f[b]) 29 { 30 num[++g] = a; 31 } 32 } 33 for(i = 0 ; i <= num[1]*o[num[1]] &&i<=n; i += num[1]) 34 c1[i] = 1; 35 for(i = 2 ; i <= g ;i++) 36 { 37 for(j = 0 ; j <= n ; j++) 38 for(e = 0 ; e+j<=n&&e <= num[i]*o[num[i]] ; e+=num[i]) 39 { 40 c2[j+e]+=c1[j]; 41 } 42 for(j = 0 ; j <= n ;j++) 43 { 44 c1[j] = c2[j]; 45 c2[j] = 0; 46 } 47 } 48 cout<<c1[n]<<endl; 49 } 50 return 0; 51 }
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define LL long long 12 #define INF 0xfffffff 13 const double eps = 1e-8; 14 const double pi = acos(-1.0); 15 const double inf = ~0u>>2; 16 double c1[22],c2[22]; 17 int b[12]; 18 int cn(int x) 19 { 20 int i,s=1; 21 for(i = 1; i <= x ; i++) 22 s*=i; 23 return s; 24 } 25 int main() 26 { 27 int i,j,n,m; 28 while(cin>>n>>m) 29 { 30 memset(c1,0,sizeof(c1)); 31 memset(c2,0,sizeof(c2)); 32 for(i = 1; i <= n; i++) 33 { 34 cin>>b[i]; 35 } 36 for(i = 0 ;i<=b[1] ;i++) 37 c1[i] = 1.0/cn(i); 38 for(i = 2; i <= n ;i++) 39 { 40 for(j = 0 ;j <= m ;j++) 41 { 42 for(int g = 0 ; g <= b[i] ; g++) 43 c2[j+g] += 1.0*c1[j]/cn(g); 44 } 45 for(j = 0 ; j <= m ;j++) 46 { 47 c1[j] = c2[j]; 48 c2[j] = 0; 49 } 50 } 51 printf("%0.lf ",c1[m]*cn(m)); 52 } 53 return 0; 54 }
hdu 1812 polya 数太大直接用JAVA了
旋转 0 n*n
90 偶数 n*n/4 奇数 (n*n-1)/4
180 偶数 n*n/2 奇数 (n*n-1)/2
270 偶数 n*n/4 奇数 (n*n-1)/4
对角折 (n*n-n)/2+n 两次
中线折 偶数 (n*n)/2 奇数(n*n-n)/2+n 两次
1 import java.text.*; 2 import java.io.*; 3 import java.util.*; 4 import java.math.*; 5 import java.applet.*; 6 public class Main 7 { 8 public static void main(String args[]) 9 { 10 BigInteger cnt; 11 Scanner cin = new Scanner(System.in); 12 int i,j,n,m; 13 while(cin.hasNextInt()) 14 { 15 n = cin.nextInt(); 16 m = cin.nextInt(); 17 cnt = BigInteger.valueOf(0); 18 BigInteger bn = BigInteger.valueOf(m); 19 cnt = cnt.add(bn.pow(n*n)); 20 if(n%2==0) 21 { 22 cnt = cnt.add(bn.pow(n*n/4).multiply(BigInteger.valueOf(2))); 23 cnt = cnt.add(bn.pow(n*n/2)); 24 cnt = cnt.add(bn.pow((n*n-n)/2+n).multiply(BigInteger.valueOf(2))); 25 cnt = cnt.add(bn.pow(n*n/2).multiply(BigInteger.valueOf(2))); 26 } 27 else 28 { 29 cnt = cnt.add(bn.pow((n*n-1)/4+1).multiply(BigInteger.valueOf(2))); 30 cnt = cnt.add(bn.pow((n*n-1)/2+1)); 31 cnt = cnt.add(bn.pow((n*n-n)/2+n).multiply(BigInteger.valueOf(4))); 32 } 33 System.out.println(cnt.divide(BigInteger.valueOf(8))); 34 } 35 } 36 }
POJ 1286 Necklace of Beads 经典的polay计数
其实对于burnside不是特别的理解 只是大体的记得了公式 大体了解 知道哪一类题是用它来解的。 下面可能会把点说成珠子。。。
文库里讲的都很清楚 可以初步了解下 这个题大体说一下 抛开重复不说 对于每个点可以染k种颜色 那么可以染的可能为n^k 因为旋转或者翻转使得一些可能变成了相同的 这时候就要删除相同的 引入置换的概念 举个例子就是在某种置换下 a->b c->d 也就是说本来该是 4^k 现在对折置换之后 a与b c与d 其实是一样的 那么很明显就变成了2^k。
这个题 包括两种置换 一是 旋转置换 二是 翻转置换
对于旋转: 套定理 k^gcd(i,n) (0<i<=n)
对于翻转: 因为要对折 就要考虑奇数 和偶数 奇数: 沿穿过每个珠子的线对折 n个置换 ((n-1)/2+1)^k
偶数 沿穿过珠子的线 n/2个置换 ((n-2)/2+2)^k 不穿过珠子的线 n/2个置换 (n/2)^k
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int gcd(int a,int b) 18 { 19 return b==0?a:gcd(b,a%b); 20 } 21 int main() 22 { 23 int i,n; 24 while(cin>>n) 25 { 26 if(n==-1) break; 27 LL s = 0; 28 if(n==0) 29 { 30 cout<<"0 "; 31 continue; 32 } 33 for(i = 1 ; i <= n ;i++) 34 { 35 s+=(LL)pow(3.0,gcd(i,n)); 36 } 37 if(n%2==0) 38 cout<<(s+n/2*(LL)pow(3.0,(n-2)/2+2)+n/2*(LL)pow(3.0,n/2))/2/n<<endl; 39 else 40 cout<<(s+n*(LL)pow(3.0,(n-1)/2+1))/2/n<<endl; 41 } 42 return 0; 43 }
POJ 2409 Let it Bead 同上 其实上题的题解该是本题的 上一题的K就是为3
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int gcd(int a,int b) 18 { 19 return b==0?a:gcd(b,a%b); 20 } 21 int main() 22 { 23 int i,n,k; 24 while(cin>>k>>n) 25 { 26 if(!n&&!k) break; 27 if(n==0) 28 { 29 cout<<"0 "; 30 continue; 31 } 32 LL s = 0; 33 for(i = 1 ; i <= n ;i++) 34 { 35 s+=(LL)pow(k*1.0,gcd(i,n)); 36 } 37 if(n%2==0) 38 cout<<(s+n/2*(LL)pow(k*1.0,(n-2)/2+2)+n/2*(LL)pow(k*1.0,n/2))/2/n<<endl; 39 else 40 cout<<(s+n*(LL)pow(k*1.0,(n-1)/2+1))/2/n<<endl; 41 } 42 return 0; 43 }
POJ 1026 Cipher 这个属于置换群的题 找出循环节 总循环节就等于lcm(x1,x2,x3) 所有的循环节的最小公倍数
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<cmath> 7 using namespace std; 8 #define LL long long 9 LL gcd(LL a,LL b) 10 { 11 return b==0?a:gcd(b,a%b); 12 } 13 char s[210],ss[210]; 14 int a[210],q[210][210],o[210]; 15 int b[210]; 16 bool vis[210]; 17 int main() 18 { 19 int i,j,n,m; 20 while(cin>>n) 21 { 22 if(!n) break; 23 memset(vis,0,sizeof(vis)); 24 for(i = 1; i <= n ;i++) 25 scanf("%d",&a[i]); 26 int kk = 0; 27 for(i = 1; i <= n; i++) 28 { 29 if(!vis[i]) 30 { 31 kk++; 32 int g = 0; 33 q[kk][++g] = i; 34 vis[i]=1; 35 int x = a[i]; 36 while(!vis[x]) 37 { 38 vis[x] = 1; 39 q[kk][++g] = x; 40 x = a[x]; 41 } 42 o[kk] = g; 43 } 44 } 45 LL lcm = 1; 46 for(i = 1; i <= kk ; i++) 47 { 48 lcm = lcm/gcd(lcm,o[i])*o[i]; 49 } 50 while(scanf("%d%*c",&m)!=EOF) 51 { 52 if(!m) break; 53 gets(s); 54 int k = strlen(s); 55 for(i = k ; i < n ;i++) 56 s[i] = ' '; 57 s[n] = '