话不多说,直接看题:
1.辗转相减法
我们不妨假设原等比数列a,a*(q/p),a*(q/p)^2....
那么x1,,,,xn就是其中的n项,xi/x1=(q/p)^b,假设最大比例为(q/p)^k,,那么一定有(q/p)^(k*s)=(q/p)^b,即k是b的因子,这样子问题就成了求b1,...bn的gcd,那么我们如何求?
我们直接求b的gcd?但是我们知道(q/p)^b但不知道里面各个量是多少,因此无法求。
我们不妨先拆成q^b/p^b,就是求q^b的gcd,我们令f[q^b1][q^b2]=q^(b1,b2).
由(a,b)=(b,a-b)知f[q^b1][q^b2]=f[q^b2][q^b1/q^b2],这样递推即可。
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=110;
int n;
LL a[N],b[N],x[N];
LL gcd(LL a,LL b){return b ? gcd(b,a%b) : a;
}
LL gg(LL a,LL b){if (a < b) swap(a, b);if (b == 1) return a;return gg(b, a / b);
}
int main(){cin>>n;for(int i=0;i<n;i++) cin>>x[i];sort(x,x+n);int cnt=0;for(int i=1;i<n;i++){if(x[i]==x[i-1]) continue;LL d=gcd(x[i],x[0]);a[cnt]=x[i]/d;b[cnt]=x[0]/d;cnt++;}LL up=a[0],down=b[0];for(int i=1;i<cnt;i++){up=gg(up,a[i]);down=gg(down,b[i]);}cout<<up<<"/"<<down;
}
2.扩展欧几里得:
转化一下就是:
解最小的正数x,xC-y*2^k=B-A
我们记C=a,2^k=b,那么x=x0+k*b/d;
这样我们把值%b/d+b/d即可。
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL exgcd(LL a,LL b,LL &x,LL &y){if(b==0){x=1,y=0;return a;}LL d=exgcd(b,a%b,y,x);y-=a/b*x;return d;
}
int main(){LL a,b,c,k;while(cin>>a>>b>>c>>k,a||b||c||k){LL x,y;LL z=1ll<<k;LL d=exgcd(c,z,x,y);if((b-a)%d) cout<<"FOREVER"<<endl;else{x*=(b-a)/d;z/=d;cout<<(x%z+z)%z<<endl;}}
}
3.递归
a|b表示选a或选b,括号即定义顺序,我们令&表示相连。
我们先看一下递归树,对于样例,有:
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
int k;
string s;
int dfs(){int res=0;while(k<s.size()){if(s[k]=='('){k++;res+=dfs();k++;//跳过)}else if(s[k]=='|'){k++;res=max(res,dfs());}else if(s[k]==')') break;else{res++;k++;}}return res;
}
int main(){cin>>s;cout<<dfs();
}
4.重复覆盖问题:
先形象一下:
我们先看1,1要被覆盖,必选1,2,3,6(至少选一个),然后我们就枚举递归
我们考虑一下优化:
1.迭代加深:枚举下答案(答案1行不,不行的话2可以吗?)
2.我们先枚举选择最少的点(如4,只有5满足)
3.可行性剪枝:
先判断一下最少还要多少(相当于在1时把1236全选),将他与剩余的行数比较
4.位运算
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N=110,M=1<<20;
int n,m,k;
vector<int> col[N];//每一列包含哪几行
int logg2[M];
int lowbit(int x){return x&-x;
}
int h(int state){//最少几行int res=0;for(int i=(1<<m)-1-state;i;i-=lowbit(i)){int c=logg2[lowbit(i)];res++;for(auto row:col[c]) i&=~row;}return res;
}
bool dfs(int dep,int state){if(!dep||h(state)>dep) return state==(1<<m)-1;//只有state满时才可能//找到选择minint t=-1;for(int i=(1<<m)-1-state;i;i-=lowbit(i)){int c=logg2[lowbit(i)];if(col[c].size()<col[t].size()||t==-1) t=c;}for(auto row:col[t]){if(dfs(dep-1,state|row)) return 1;}return 0;
}
int main(){cin>>n>>m>>k;for(int i=0;i<m;i++) logg2[1<<i]=i;for(int i=0;i<n;i++){int state=0;for(int j=0;j<k;j++){int c;scanf("%d",&c);state|=1<<(c-1);}for(int j=0;j<m;j++){if(state>>j&1){col[j].push_back(state);}}}for (int i = 0; i < m; i ++ ){sort(col[i].begin(), col[i].end());col[i].erase(unique(col[i].begin(), col[i].end()), col[i].end());//unique把重复元素放后,返回第一个重复的迭代器;}int dep=0;while(dep<=m&&!dfs(dep,0)) dep++;//迭代加深,层数就是选的糖果数if(dep>m) dep=-1;cout<<dep;
}