100道codeforces 2500
首先小小容斥一下,用1~r的减去1~l-1的。 1~r的,可以想到数位dp 设f[len][pre][mod]表示从低位数第len位,当前数字的值%2450为pre,当前用过的数字的lcm为mod的方案数 使用limit表示是否贴着上界 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int mod=998244353;//1e9+7 ll read(){ll x;scanf("%lld",&x);return x;} ll quick(ll a,ll b){ll t=1;while(b){if(b&1)t=t*a%mod;b=b/2;a=a*a%mod;}return t;} int lowbit(int x){return x&(-x);} int digit[20],mp[2521]; ll f[20][2521][50]; ll dfs(int len,int pre,int mod,int limit) { if(!len) return pre%mod==0; if(!limit&&f[len][pre][mp[mod]]!=-1) return f[len][pre][mp[mod]]; ll ret=0; int ed=limit?digit[len]:9; for(int i=0;i<=ed;i++) ret+=dfs(len-1,(pre*10+i)%2520,i==0?mod:mod/__gcd(mod,i)*i,limit&&i==ed); if(!limit) f[len][pre][mp[mod]]=ret; return ret; } ll ask(ll x) { int len=0; while(x) {digit[++len]=x%10;x=x/10; } return dfs(len,0,1,1); } void work() { memset(f,-1,sizeof(f)); ll l=read(),r=read(); cout<<ask(r)-ask(l-1)<<'\n'; } int main() { int cnt=0; for(int i=1;i<=2520;i++) if(2520%i==0) mp[i]=++cnt; for(int t=read();t;t--) work(); }
例如,我们把abc看成是 从ab点移动到了bc点 则恢复密码只需要跑欧拉路即可。抄了刘瑾豪的模板然后发现他模板错了,非常难崩 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=200010,mod=998244353;//1e9+7; ll read(){ll x;scanf("%lld",&x);return x;} ll quick(ll a,ll b){ll t=1;while(b){if(b&1)t=t*a%mod;b=b/2;a=a*a%mod;}return t;} int lowbit(int x){return x&(-x);} int n,ans[N*2],chu[N],ru[N],tot,cur[N]; vector<int>e[N]; void dfs(int x) { while(cur[x]<e[x].size()) { int t=cur[x]; cur[x]++; dfs(e[x][t]); } ans[++tot]=x; } int main() { int n1=n=read(); for(int i=1;i<=n;i++) { string s; cin>>s; int x=s[0]*130+s[1],y=s[1]*130+s[2]; e[x].push_back(y); ru[y]++; chu[x]++; } n=130*130; int root=-1,cnt=0; for(int i=n;i>=0;i--) { if(abs(ru[i]-chu[i])>1) { cout<<"NO"; return 0; } if(ru[i]!=chu[i]) cnt++; } if(cnt!=0&&cnt!=2) cout<<"NO"; else { if(cnt==2) for(int i=0;i<=n;i++) if(ru[i]<chu[i]) root=i; if(root==-1) { for(int i=0;i<=n;i++) if(ru[i]) root=i; } dfs(root); if(n1+1!=tot) cout<<"NO"; else { cout<<"YES\n"; cout<<char(ans[tot]/130); for(int i=tot;i;i--) cout<<char(ans[i]%130); } } }
考虑根号分治 如果询问长度小于s就暴力,复杂度为O(qs) 如果询问长度大于s,就暴力枚举出现次数大于s/k的那些数字,询问他们在询问中出现了几次,复杂度为qn/s*5logn 跑的飞快 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=300010; int lowbit(int x){return x&(-x);} ll read(){ll x;scanf("%lld",&x);return x;} int n,q,s,a[N],cnt[N]; struct node { int siz,v; friend bool operator <(node a,node b) { return a.siz>b.siz; } }; vector<node>o; vector<int>pos[N]; int ask(int l,int r,int v) { auto b=upper_bound(pos[v].begin(),pos[v].end(),r); auto a=lower_bound(pos[v].begin(),pos[v].end(),l); return b-a; } int main() { n=read();q=read(); s=sqrt(2.5*n); for(int i=1;i<=n;i++) { a[i]=read(); pos[a[i]].push_back(i); } for(int i=1;i<=n;i++) if(pos[i].size()>=s/5) o.push_back({pos[i].size(),i}); sort(o.begin(),o.end()); for(int i=1;i<=q;i++) { int l=read(),r=read(),k=read(); int len=(r-l+1)/k; if(r-l+1<=s) { int ans=1e6; for(int j=l;j<=r;j++) cnt[a[j]]++; for(int j=l;j<=r;j++){ if(cnt[a[j]]>len) ans=min(ans,a[j]); cnt[a[j]]--; } if(ans==1e6) ans=-1; cout<<ans<<'\n'; } else { int ans=1e6; for(auto [siz,v]:o) { if(siz<=len) break; int num=ask(l,r,v); if(num>len) ans=min(ans,v); } if(ans==1e6) ans=-1; cout<<ans<<'\n'; } } }
首先,交换aiaj,如果ai不等于aj,必使得逆序对数量奇偶变化 但是这题并没有用 考虑把逆序对放在左端点的vector上 然后从小到大地枚举以i位左端点的逆序对,大胆交换,可以使得相关右端点往前整体挪一位,ai放在了相关右端点的最右边 一直做下去,最后一定会单调的 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=100010; int lowbit(int x){return x&(-x);} ll read(){ll x;scanf("%lld",&x);return x;} int n,a[N],cnt; struct node { int v,i; friend bool operator <(node a,node b) { return a.v==b.v?a.i<b.i:a.v<b.v; } }; vector<node>b,o[N]; int main() { n=read(); for(int i=1;i<=n;i++) { a[i]=read(); b.push_back({a[i],i}); } sort(b.begin(),b.end()); for(int i=1;i<n;i++) for(int j=i+1;j<=n;j++) if(a[i]>a[j]) { o[i].push_back({0,j}); cnt++; } cout<<cnt<<'\n'; for(auto [v,i]:b) { if(o[i].empty()) continue; reverse(o[i].begin(),o[i].end()); for(auto [val,j]:o[i]) { cout<<i<<' '<<j<<'\n'; swap(a[i],a[j]); } } } // 把逆序对找出来,排序 // 然后依次枚举每个逆序对,交换 // 问最后能不能变成有序的 // 比如 // // 3 1 2 // 1 2 // 2 3 // 1 3 // // // // 先1 2 // 1 3 2 // 2 3 1 // 2 1 3 // // // 原来奇数个,交换aiaj

浙公网安备 33010602011771号