给定 ,求出
并且
要最小,
,满足
可以写成
,根据
可以推出
即,因为
,所以两边可以减去最大的整数
.
变成,再倒过来变成
,重复以上步骤直到两端点之间有整数时
取最小的整数,
,所以可以用辗转相除法得到.
#include<bits/stdc++.h> #define me(a,x) memset(a,x,sizeof(a)) #define sc scanf #define itn int #define IN freopen("in.txt","r",stdin); #define OUT freopen("out.txt","w",stdout); #define STR clock_t startTime = clock(); #define END clock_t endTime = clock();cout << double(endTime - startTime) / CLOCKS_PER_SEC *1000<< "ms" << endl; using namespace std; const int N=1e6; const long long mod=1e9+7; const long long mod2=998244353; const int oo=0x7fffffff; const int sup=0x80000000; typedef long long ll; typedef unsigned long long ull; template <typename it>void db(it *begin,it *end){while(begin!=end)cout<<(*begin++)<<" ";puts("");} template <typename it> string to_str(it n){string s="";while(n)s+=n%10+'0',n/=10;reverse(s.begin(),s.end());return s;} template <typename it>int o(it a){cout<<a<<endl;return 0;} ll mul(ll a,ll b,ll c){ll ans=0;for(;b;b>>=1,a=(a+a)%c)if(b&1)ans=(ans+a)%c;return ans;} ll ksm(ll a,ll b,ll c){ll ans=1;for(;b;b>>=1,a=mul(a,a,c))if(b&1)ans=mul(ans,a,c);return ans;} void dfs(ll p1,ll x1,ll p2,ll x2,ll &b,ll &y){ ll z=p1/x1+1; if(z<=p2/x2){ b=z,y=1; return ; } p1-=(z-1)*x1;p2-=(z-1)*x2; dfs(x2,p2,x1,p1,y,b); b+=(z-1)*y;//原式减去了(z-1)*y,要加回. } int main(){ //STR; //IN OUT int t;cin>>t; while(t--){ ll p,x; sc("%lld%lld",&p,&x); ll a,b,y; dfs(p,x,p,x-1,b,y); a=b*x-p*y; printf("%lld/%lld\n",a,b); } //END }
HDU-6625 three arrays
给定个数组
,要求一个
数组,
数组中的数可以由
数组各选一个数异或得到,求
数组,最小字典序输出.
数组分别建一棵
,每次贪心取
,若都没有相同的则随便往哪条支路走.
#include<bits/stdc++.h> #define me(a,x) memset(a,x,sizeof(a)) #define sc scanf #define itn int using namespace std; const int N=2e6; const long long mod=1e9+7; const long long mod2=998244353; const int oo=0x7fffffff; const int sup=0x80000000; typedef long long ll; typedef unsigned long long ull; template <typename it>void db(it *begin,it *end){while(begin!=end)cout<<(*begin++)<<" ";puts("");} template <typename it> string to_str(it n){string s="";while(n)s+=n%10+'0',n/=10;reverse(s.begin(),s.end());return s;} template <typename it>int o(it a){cout<<a<<endl;return 0;} ll mul(ll a,ll b,ll c){ll ans=0;for(;b;b>>=1,a=(a+a)%c)if(b&1)ans=(ans+a)%c;return ans;} ll ksm(ll a,ll b,ll c){ll ans=1;for(;b;b>>=1,a=mul(a,a,c))if(b&1)ans=mul(ans,a,c);return ans;} int Trie[2][N][2]; int val[2][N]; int a[N],b[N],tot[2]; void insert(int op,int x){ int next=0; for(int i=30;i>=0;i--){ int key=x>>i&1; if(Trie[op][next][key]==0){ Trie[op][next][key]=++tot[op]; Trie[op][Trie[op][next][key]][0]=0; Trie[op][Trie[op][next][key]][1]=0; } next=Trie[op][next][key]; val[op][next]++; } } int QAQ(){ int ans=0; int nx1=0,nx2=0; for(int i=30;i>=0;i--){ if(val[0][Trie[0][nx1][0]]&&val[1][Trie[1][nx2][0]]){ val[0][Trie[0][nx1][0]]--; val[1][Trie[1][nx2][0]]--; nx1=Trie[0][nx1][0]; nx2=Trie[1][nx2][0]; }else if(val[0][Trie[0][nx1][1]]&&val[1][Trie[1][nx2][1]]){ val[0][Trie[0][nx1][1]]--; val[1][Trie[1][nx2][1]]--; nx1=Trie[0][nx1][1]; nx2=Trie[1][nx2][1]; }else if(val[0][Trie[0][nx1][0]]&&val[1][Trie[1][nx2][1]]){ ans+=1<<i; val[0][Trie[0][nx1][0]]--; val[1][Trie[1][nx2][1]]--; nx1=Trie[0][nx1][0]; nx2=Trie[1][nx2][1]; }else if(val[0][Trie[0][nx1][1]]&&val[1][Trie[1][nx2][0]]){ ans+=1<<i; val[0][Trie[0][nx1][1]]--; val[1][Trie[1][nx2][0]]--; nx1=Trie[0][nx1][1]; nx2=Trie[1][nx2][0]; } } return ans; } int main(){ //clock_t startTime = clock(); //freopen("in.txt","r",stdin); me(val,0);me(Trie,0); int t;cin>>t; while(t--){ Trie[0][0][0]=Trie[0][0][1]=Trie[1][0][0]=Trie[1][0][1]=0; val[0][0]=0;val[1][0]=0; tot[0]=tot[1]=0; int n;sc("%d",&n); for(int i=1;i<=n;i++){sc("%d",a+i);insert(0,a[i]);} for(int i=1;i<=n;i++){sc("%d",b+i);insert(1,b[i]);} vector<int>ans; for(int i=1;i<=n;i++)ans.push_back(QAQ()); sort(ans.begin(),ans.end()); for(int i=0;i<n;i++)printf("%d%c",ans[i]," \n"[i==n-1]); } //clock_t endTime = clock(); //cout << double(endTime - startTime) / CLOCKS_PER_SEC << "s" << endl; }
给定求解方程
的根.
首先很重要的条件,每条直线的斜率大于
,如图:
根据零点分布可以划分个区间,
在其中一个区间时,左边的直线可以直接去绝对值,右边的直线去绝对值要加负号,所以可以合并成一条直线判断解是否在那个区间即可,求个
前缀和可以降低复杂度,关键点:每条直线斜率都大于
.
#include<bits/stdc++.h> #define me(a,x) memset(a,x,sizeof(a)) #define sc scanf #define itn int #define STR clock_t startTime = clock(); #define END clock_t endTime = clock();cout << double(endTime - startTime) / CLOCKS_PER_SEC *1000<< "ms" << endl; using namespace std; const int N=1e6; const long long mod=1e9+7; const long long mod2=998244353; const int oo=0x7fffffff; const int sup=0x80000000; typedef long long ll; typedef unsigned long long ull; template <typename it>void db(it *begin,it *end){while(begin!=end)cout<<(*begin++)<<" ";puts("");} template <typename it> string to_str(it n){string s="";while(n)s+=n%10+'0',n/=10;reverse(s.begin(),s.end());return s;} template <typename it>int o(it a){cout<<a<<endl;return 0;} ll mul(ll a,ll b,ll c){ll ans=0;for(;b;b>>=1,a=(a+a)%c)if(b&1)ans=(ans+a)%c;return ans;} ll ksm(ll a,ll b,ll c){ll ans=1;for(;b;b>>=1,a=mul(a,a,c))if(b&1)ans=mul(ans,a,c);return ans;} itn n,c; ll sa[N]={0},sb[N]={0}; struct node{ int a,b; bool friend operator <(node x,node y){ return x.b*y.a>x.a*y.b; } }line[N]; int main(){ //STR //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int t;cin>>t; while(t--){ sc("%d%d",&n,&c); for(int i=1;i<=n;i++){ sc("%d%d",&line[i].a,&line[i].b); } sort(line+1,line+1+n); for(int i=1;i<=n;i++)sa[i]=sa[i-1]+line[i].a,sb[i]=sb[i-1]+line[i].b; vector<pair<ll,ll>>Q; if(sa[n]==0&&(-sb[n]==c||sb[n]==c)){ o(-1);continue; } if(sa[n]!=0&&1LL*line[1].a*(c+sb[n])>=1LL*line[1].b*sa[n]){ ll x=sb[n]+c,y=-sa[n]; ll g=__gcd(x,y); x/=g,y/=g; if(y<0)x=-x,y=-y; Q.push_back({x,y}); } bool BOOl=false; for(int i=1;i<n;i++){ ll ai=2LL*sa[i]-sa[n],bi=2LL*sb[i]-sb[n]; if(ai==0&&c==bi){BOOl=true;o(-1);break;} if(ai!=0){ if(-line[i].b*1.0/line[i].a<(c-bi)*1.0/ai&&(c-bi)*1.0/ai<=-line[i+1].b*1.0/line[i+1].a){ ll x=c-bi,y=ai; ll g=__gcd(x,y); x/=g,y/=g; if(y<0)x=-x,y=-y; Q.push_back({x,y}); } } } if(BOOl)continue; if(sa[n]!=0&&(0LL+c-sb[n])*line[n].a>sa[n]*(-line[n].b)){ ll x=c-sb[n],y=sa[n]; ll g=__gcd(x,y); x/=g,y/=g; if(y<0)x=-x,y=-y; Q.push_back({x,y}); } int sz=unique(Q.begin(),Q.end())-Q.begin(); printf("%d",sz); for(int i=0;i<sz;i++)printf(" %lld/%lld",Q[i].first,Q[i].second); puts(""); }//END }
找出一个排列的字典序第
小排列输出.字典序判断标准是
.
因为最大时
,所以
时直接按合法序列输出,
时暴力即可.
#include<bits/stdc++.h> #define me(a,x) memset(a,x,sizeof(a)) #define sc scanf #define itn int #define cas int t;cin>>t;while(t--) using namespace std; const int N=1e6; const long long mod=1e9+7; const int oo=0x7fffffff; const int sup=0x80000000; typedef long long ll; typedef unsigned long long ull; template <typename it>void db(it *begin,it *end){while(begin!=end)cout<<(*begin++)<<" ";puts("");} template <typename it> string to_str(it n){string s="";while(n)s+=n%10+'0',n/=10;reverse(s.begin(),s.end());return s;} template <typename it>int o(it a){cout<<a<<endl;return 0;} ll mul(ll a,ll b,ll c){ll ans=0;for(;b;b>>=1,a=(a+a)%c)if(b&1)ans=(ans+a)%c;return ans;} ll ksm(ll a,ll b,ll c){ll ans=1;for(;b;b>>=1,a=mul(a,a,c))if(b&1)ans=mul(ans,a,c);return ans;} bool cmp(vector<pair<int,int> >a,vector<pair<int,int> >b){ int sz=a.size(); for(int i=0;i<sz;i++){ if(a[i].second==b[i].second)continue; if(a[i].second<b[i].second)return true; else return false; } } int main(){ //freopen("in.txt","r",stdin); cas{ int n,k; sc("%d%d",&n,&k); if(n>8){ vector<int>a; for(int i=1;i<n;i++)a.push_back(i); do{ k--; if(k==0){ printf("%d",n); for(int x:a)printf(" %d",x); puts(""); break; } }while(next_permutation(a.begin(),a.end())); }else{ vector<vector<pair<int,int> > >a; vector<int>all; for(int i=1;i<=n;i++)all.push_back(i); do{ vector<pair<int,int> >x; for(int i=0;i<n;i++){ if(i){ x.push_back({all[i],all[i]-all[i-1]}); }else x.push_back({all[i],0}); } a.push_back(x); }while(next_permutation(all.begin(),all.end())); sort(a.begin(),a.end(),cmp); for(int i=0;i<n;i++)printf("%d%c",a[k-1][i].first," \n"[i==n-1]); } } }
输出比较次数.
扩展数组的性质
#include<bits/stdc++.h> #define me(a,x) memset(a,x,sizeof(a)) #define sc scanf #define itn int using namespace std; const int N=1e6+5; const long long mod=1e9+7; const long long mod2=998244353; const int oo=0x7fffffff; const int sup=0x80000000; typedef long long ll; typedef unsigned long long ull; template <typename it>void db(it *begin,it *end){while(begin!=end)cout<<(*begin++)<<" ";puts("");} template <typename it> string to_str(it n){string s="";while(n)s+=n%10+'0',n/=10;reverse(s.begin(),s.end());return s;} template <typename it>int o(it a){cout<<a<<endl;return 0;} ll mul(ll a,ll b,ll c){ll ans=0;for(;b;b>>=1,a=(a+a)%c)if(b&1)ans=(ans+a)%c;return ans;} ll ksm(ll a,ll b,ll c){ll ans=1;for(;b;b>>=1,a=mul(a,a,c))if(b&1)ans=mul(ans,a,c);return ans;} char s[N]; int ex[N]; int main(){ int t;cin>>t; while(t--){ sc("%s",s); int mix=0,L=0; int n=strlen(s); for(int i=1;i<n;i++){ if(i>=mix)ex[i]=0; else ex[i]=min(mix-i,ex[i-L]); while(s[ex[i]]==s[ex[i]+i])ex[i]++; if(i+ex[i]>mix)mix=i+ex[i],L=i; } ll ans=0; for(int i=1;i<n;i++){ ans++; if(ex[i]){ ans+=ex[i]; if(i+ex[i]==n)ans--; } if(i+ex[i]>n)break; } printf("%lld\n",ans); } }
排列满足以下关系:
这样的排列有多少个
没有限制的时候可以得到递推关系:
#include<bits/stdc++.h> using namespace std; const int N=100005; int a[N]; void init() { a[1]=1;a[2]=1;a[3]=1; for(int i=4;i<N;i++) a[i]=(a[i-1]+a[i-3])%998244353; } int main() { init(); int t; scanf("%d",&t); while(t--) { int n,x,y; scanf("%d%d%d",&n,&x,&y); if(x==1) { if(y==n) printf("%d\n",a[y]); else printf("%d\n",a[y-1]); }else if(y==n) { printf("%d\n",a[y-x]); }else { printf("%d\n",a[y-x-1]); } } }