由于本Cho太过懒惰,不再更新之前已经AC以及个人认为没有很大必要写的题目;

请善用 Ctrl + F qwq

排名先后仅看做题顺序

 

#1.1 1085 背包问题

01背包模板

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 
 5 int n,maxx,DP[1000000],w,v;
 6 
 7 int main(){
 8     scanf("%d%d",&n,&maxx);
 9     
10     for(int i = 1;i <= n;i++){
11         scanf("%d%d",&w,&v);
12         for(int j = maxx;j >= w;j--)
13             DP[j] = max(DP[j],DP[j-w]+v);
14     }
15     
16     cout << DP[maxx];
17     
18     return 0;
19 }
01背包 + 一维表示

#1.2 1086 背包问题 V2

多重背包 + 二进制优化

什么是二进制优化呢?当前物品有数量 c ,将其拆分成 1 2 4 8 16 ... (剩下) ,然后一个个做01背包

决策每一个数字的时候 (1,2,4...) ,选与不选,相当于该物品已有数量加不加当前数字,而我们将决策 c 的二进制表示的每一位,那么所有的 1,2,4,... 是可以组合表示出 ≤c 的所有数量的状态的

这样就优化成一层 log 

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 
 5 int n,maxx,DP[1000000],w,v,c;
 6 
 7 int main(){
 8     scanf("%d%d",&n,&maxx);
 9     
10     for(int i = 1;i <= n;i++){
11         scanf("%d%d%d",&w,&v,&c);
12         int d = 1;
13         while(d <= c){
14             for(int j = maxx;j >= d*w;j--)
15                 DP[j] = max(DP[j],DP[j-d*w]+d*v);
16             c -= d;
17             d *= 2;
18         }for(int j = maxx;c && j >= c*w;j--)
19             DP[j] = max(DP[j],DP[j-c*w]+c*v);
20     }
21     
22     cout << DP[maxx];
23     
24     return 0;
25 }
二进制优化 + 一维表示

#1.3 1257 背包问题 V3

跟分数规划打了场遭遇战= =

数学分析目标式,二分答案

此处解题报告 [51nod] 1257 背包问题 V3

 1 #include<stdio.h>
 2 #include<math.h>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 int n,k;
 8 long long ansv,answ;
 9 
10 double eps = 0.000000001;
11 
12 struct data{
13     long long w,v;
14     double vrw;
15 }arr[1000000];
16 
17 bool cmp(const data &a,const data &b){ return a.vrw > b.vrw; }
18 
19 bool check(long long &sumv,long long &sumw,double line){
20     for(int i = 1;i <= n;i++)
21         arr[i].vrw = 1.0*arr[i].v-line*arr[i].w;
22     
23     sort(arr+1,arr+1+n,cmp);
24     
25     double tmp = 0;
26     sumv = 0,sumw = 0;
27     for(int i = 1;i <= k;i++)
28         sumv += arr[i].v,
29         sumw += arr[i].w,
30         tmp += arr[i].vrw;
31     
32     return tmp >= 0;
33 }
34 
35 long long gcd(long long a,long long b){
36     if(a < b) swap(a,b);
37     return !b?a:gcd(b,a%b);
38 }
39 
40 int main(){
41     
42     scanf("%d%d",&n,&k);
43     
44     for(int i = 1;i <= n;i++)
45         scanf("%lld%lld",&arr[i].w,&arr[i].v);
46     
47     double L = 0,R = 1000000;
48     long long sumv,sumw;
49     while(R-L > eps){
50 //        printf("%.8lf %.8lf\n",L,R);
51         double mid = (L+R)/2;
52         if(check(sumv,sumw,mid)) ansv = sumv, answ = sumw, L = mid;
53         else R = mid;
54     }
55     
56     long long d = gcd(ansv,answ);
57     printf("%lld/%lld",ansv/d,answ/d);
58     
59     return 0;
60 }
分数规划

#2.1 1136 欧拉函数

Emmmm,现在有 m 与 p 互质且 p 为质数,那么 phi( p ) = p-1 ,phi( mp ) = phi( m )*phi( p ) = phi( m )*( p-1 )

然后对于 phi( mpp ) = phi( mp )*p

Emmmm 这个我居然没法证明

我们知道如果 phi( mpp ) = phi ( mp )* ??? ,那么 ??? = phi( mpp ) / phi( mp )

而 mpp 和 mp 的质因子是一样的

所以根据公式 phi ( x ) = x*(1-.........) 我们知道对于 x 后面的部分,phi ( mpp ) 和 phi ( mp )是相同的,那么两元相除得 phi ( mpp ) / phi ( mp ) = p

 1 #include<stdio.h>
 2 #include<iostream>
 3 using namespace std;
 4 
 5 //int prime[100000],primesize;
 6 //bool isprime[100000];
 7 //void getlist(int listsize){
 8 //    listsize = (int)sqrt(listsize)+10;
 9 //    isprime[
10 //}
11 
12 int phi(int &x){
13     int ans = 1;
14     for(int i = 2;i*i <= x;i++){
15         if(x%i) continue;
16         ans *= (i-1);
17         x /= i;
18         while(x%i == 0){
19             ans *= i;
20             x /= i;
21         }
22     }if(x > 1) ans *= x-1; // 这条和 i*i <= x 可以防止x为大质数导致TLE
23     return ans;
24 }
25 
26 int main(){
27     int n;
28     scanf("%d",&n);
29     
30     cout << phi(n);
31     
32     return 0;
33 }
朴素欧拉函数

#3.1 1242 斐波那契数列的第N项

矩阵快速幂

 1 #include<cstdio>
 2 #include<iostream>
 3 #define mod 1000000009
 4 using namespace std;
 5 
 6 struct MAT{
 7     long long d[5][5];
 8     MAT(){ d[1][1] = d[1][2] = d[2][1] = d[2][2] = 0; }
 9     void Init(){ 
10         d[1][2] = d[2][1] = d[2][2] = 1;
11         d[1][1] = 0;
12     }
13 }I;
14 
15 MAT mul(MAT A,MAT B){
16     MAT C;
17     for(int i = 1;i <= 2;i++)
18         for(int j = 1;j <= 2;j++)
19             for(int k = 1;k <= 2;k++)
20                 C.d[i][j] = (C.d[i][j]+A.d[i][k]*B.d[k][j]%mod)%mod;
21     return C;
22 }
23 
24 MAT ksm(MAT A,long long k){
25     MAT B = A;
26     k--;
27     while(k){
28         if(k&1) B = mul(B,A);
29         A = mul(A,A);
30         k >>= 1;
31     }return B;    
32 }
33 
34 int main(){
35     long long n;
36     scanf("%lld",&n);
37     
38     if(n <= 2) return printf("1"),0;
39     
40     MAT I;
41     I.Init();
42     
43     I = ksm(I,n-1);
44     
45     long long c = (I.d[1][1]+I.d[1][2])%mod;
46     
47     cout << c;
48     
49     return 0;
50 }
矩阵快速幂

#4 1106 质数检测

Miller-Rabbin 素性测试,二次探测才是核心 

 1 #include<stdio.h>
 2 #include<iostream>
 3 #define LL long long
 4 using namespace std;
 5 
 6 int prime[8] = {2,3,5,7,11,13,17,19};
 7 
 8 LL ksm(LL x,LL k,LL m){
 9     if(k == 1) return x%m;
10     if(!k) return 1;
11     LL b = 1;
12     while(k){
13         if(k&1) b = b*x%m;
14         x = x*x%m;
15         k >>= 1;
16     }return b%m;
17 }
18 
19 bool TD(LL x,LL a){
20     if(x == a) return true;
21     LL m = x-1;
22     while(m % 2 == 0) m >>= 1;
23     LL t = ksm(a,m,x);
24     while(m != x-1 && t != 1 && t != x-1)
25         t = t*t%x,m <<= 1;
26     return (m&1 || t == x-1);
27 }
28 
29 bool isPrime(LL x){
30     if(x == 2) return true;
31     if(x < 1 || x % 2 == 0) return false;
32     for(int i = 0;i < 8;i++)
33         if(!TD(x,prime[i])) return false;
34     return true;
35 }
36 
37 int main(){
38     int n;
39     scanf("%d",&n);
40     
41     for(int i = 1;i <= n;i++){
42         long long x; scanf("%lld",&x);
43         if(isPrime(x)) printf("Yes\n");
44         else printf("No\n");
45     }
46     
47     return 0;
48 }
Miller Rabbin

相关文章: