------------恢复内容开始------------
7-1 1A. 期望逆序对
对每一对按期望排序即可(猜出来的,很好证明)
#include <iostream> #include <map> #include <algorithm> #include <string.h> using namespace std; const int maxn=5e3+10; typedef long long ll; const int mod=998244353; ll len[maxn]; ll inv2; ll qp(ll a,ll b,ll mod) { ll ans=1; while(b) { if(b&1) ans=(ans*a)%mod; a=(a*a)%mod; b>>=1; } return ans; } ll J(ll l1,ll r1,ll l2,ll r2,int i,int j) { ll ans=0; if(r1>r2) { ans=(r1-r2)*(r2-l2+1)%mod; } if(l2<l1) { ans=(ans+(l1-l2)*(r1-l1+1))%mod; } // ans=(ans-max(0ll,l1-l2)*max(0ll,r1-r2)+mod)%mod; ll shang=min(r1,r2),xia=max(l1,l2); ll l=shang-xia+1; if(shang>xia) { ans=((ans+(l*l-l)%mod*inv2)%mod+mod)%mod; } return ((ans*len[i])%mod*len[j])%mod; } typedef pair<ll, ll> P; P a[maxn]; bool cmp(P a1,P a2) { if(a1.first+a1.second<a2.first+a2.second) return 1; else return 0; } ll n; int main() { inv2=qp(2, mod-2, mod); // cout<<(3*qp(8, mod-2, mod))%mod; scanf("%lld",&n); for(ll i=0;i<n;i++) scanf("%lld%lld",&a[i].first,&a[i].second); // cin>>a[i].first>>a[i].second; sort(a, a+n, cmp); for(int i=0;i<n;i++) { len[i]=qp(a[i].second-a[i].first+1, mod-2, mod); } ll ans=0; for(ll i=0;i<n;i++){ for(ll j=i+1;j<n;j++) { ll t=J(a[i].first, a[i].second, a[j].first, a[j].second,i,j); // cout<<a[i].first<<a[i].second<<a[j].first<<a[j].second<<" "<<t<<endl; ans=(ans+t)%mod; } } printf("%lld\n",ans); }
7-2 1B. 密码学
签到
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; char s[1002][1002]; struct hh{ int x,y; }a[2001]; int n,m; bool daxie(char x){ if(x >= 'A' && x <= 'Z') return true; else return false; } char zhuan(char a,char b){ int x,y; if(daxie(a)) x = a - 'A' + 26; else x = a - 'a'; if(daxie(b)) y = b - 'A' + 26; else y = b - 'a'; int c = (y - x + 52) % 52; if(c <= 25) c += 'a'; else c += 'A' - 26; return (char)c; } void calc(int a,int b){ char s2[1003]; int cnt = 0,n1 = strlen(s[a]),m1 = strlen(s[b]); if(n1 < m1) while(cnt < m1){ for(int i = 0;i < n1;i ++) s2[i + cnt] = s[a][i]; cnt += n1; } else strcpy(s2,s[a]); for(int i = 0;i < m1;i ++) s[b][i] = zhuan(s2[i],s[b][i]); return; } void solve(){ cin >> n >> m; for(int i = 1;i <= m;i ++) scanf("%d%d",&a[i].x,&a[i].y); for(int i = 1;i <= n;i ++) scanf("%s",s[i]); for(int i = m;i >= 1;i --) calc(a[i].x,a[i].y); for(int i = 1;i <= n;i ++) printf("%s\n",s[i]); return; } int main(){ solve(); return 0; }
7-3 1C. 染色图
首先应该是均摊颜色不难猜出,后来推公式有点烦,把n%i拆成n-n/i*i就行了,后来就分块就可以
#include<iostream> #include<cstdio> #include<algorithm> #include<set> #include<vector> #include<bitset> #include <string.h> #include <stack> using namespace std; #define ls rt<<1 #define rs rt<<1|1 typedef long long ll; const ll maxn = 998244353; const int mod=998244353; typedef pair<double, double> P; typedef long long ll; ll qp(ll a,ll b,ll mod) { ll ans=1; while(b) { if(b&1) ans=(ans*a)%mod; a=(a*a)%mod; b>>=1; } return ans; } ll J(ll L,ll R,ll k)//k/i { //n*k- xigema i*(k/i)x; ll ans=0; for(ll l=L,r=0;l<=R;l++) { if(k/l) r=min(R,k/(k/l)); else r=R; ans=(ans+(k/l)*(r-l+1))%mod; l=r; } return ans; } ll J2(ll L,ll R,ll k)//k/i*i { //n*k- xigema i*(k/i)x; ll ans=0; for(ll l=L,r=0;l<=R;l++) { if(k/l) r=min(R,k/(k/l)); else r=R; ans=((k/l)*(((r-l+1)*(l+r)/2)%mod)+ans)%mod; l=r; } return ans; } ll J3(ll L,ll R,ll k)//k/i*(k/i)*i { //n*k- xigema i*(k/i)x; ll ans=0; for(ll l=L,r=0;l<=R;l++) { if(k/l) r=min(R,k/(k/l)); else r=R; ans=(ans+((k/l)*(k/l)%mod)*(((r-l+1)*(l+r)/2)%mod))%mod; l=r; } return ans; } int main() { int T; cin>>T; while(T--) { ll l,r,k; cin>>k>>l>>r; ll ans2=(((k*k%mod-k)*(r-l+1)%mod-2*J(l, r, k)*k+J3(l, r, k)+J2(l, r, k))%mod+mod)%mod; cout<<(ans2*qp(2, mod-2, mod))%mod<<endl; } }