T1
這題千萬不要認為是莫反題
列舉質因子\(x,y\),\(x,y<=998\),對答案的貢獻為\(min(\lfloor{\frac{B}{x}}\rfloor,\lfloor{\frac{D}{y}}\rfloor)\),再容斥一下即可
MD最後答案要取模啊
點選檢視程式碼
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
using namespace std;
const int mod=1e9+7;
ll A,B,C,D;
inline ll solve(ll B,ll D)
{
ll ans=0;
for(ll x=1;x<=998;x++)
{
for(ll y=1;y<=998;y++)
{
if(x+y>999||x>B||y>D)break;
if(__gcd(x,y)!=1)continue;
// cout<<x<<" "<<y<<endl;
// cout<<B/x+D/y<<endl;
ans=((min(B/x,D/y))*(x+y)%mod+ans)%mod;
// ans%=mod;
}
}
return ans;
}
int main()
{
speed();
cin>>A>>B>>C>>D;
ll ans=0;
// cout<<solve(B,D)<<endl;
cout<<((solve(B,D)+solve(A-1,C-1)-solve(A-1,D)-solve(B,C-1))%mod+mod)%mod<<endl;
return 0;
}
/*
5 8 3 6
999999999999 1000000000000 999999999999 1000000000000
*/
T2
讀假題了,以為是一個一個換(MD我考試在幹什麼啊)
其實就是找行之間那些匹配,同理找列之間,我們發現是有傳遞性的,如\(1行可以與2行和3行匹配\),那無論\(2,3行\)可不可以直接交換,都有一種可以透過\(1\)讓他們交換位置
點選檢視程式碼
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
using namespace std;
const int mod=998244353,N=55;
ll n,k,a[N][N];
ll jie[N],fa[N],cnt[N],cnt2[N];
int find(int x)
{
if(fa[x]!=x)fa[x]=find(fa[x]);
return fa[x];
}
int main()
{
speed();
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
cin>>n>>k;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
cin>>a[i][j];
}
jie[0]=1;
for(ll i=1;i<=n;i++)jie[i]=jie[i-1]*i%mod;
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
bool chk=1;
for(int x=1;x<=n;x++)
if(a[i][x]+a[j][x]>k){chk=0;break;}
if(chk)
{
if(find(i)!=find(j))
{
fa[find(i)]=find(j);
}
// hang[i]++;
}
}
// hang[i]++;
// cout<<i<<" "<<hang[i]<<endl;
}
ll ans=1;
for(int i=1;i<=n;i++)
{
cnt[find(i)]++;
}
for(int i=1;i<=n;i++)if(cnt[i])ans=ans*jie[cnt[i]]%mod;
// cout<<endl;
// cout<<han<<endl;
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
bool chk=1;
for(int x=1;x<=n;x++)
if(a[x][i]+a[x][j]>k){chk=0;break;}
if(chk)
{
if(find(i)!=find(j))
{
fa[find(i)]=find(j);
}
}
}
// cout<<i<<" "<<lie[i]<<endl;
}
for(int i=1;i<=n;i++)
{
cnt2[find(i)]++;
}
for(int i=1;i<=n;i++)if(cnt2[i])ans=ans*jie[cnt2[i]]%mod;
// for(int i=1;i<=n;i++)cout<<cnt2[i]<<" ";
// cout<<endl;
// if(!ans)
// {
// ans=jie[max(*max_element(cnt+1,cnt+1+n),*max_element(cnt2+1,cnt2+1+n))];
// }
cout<<ans<<endl;
return 0;
}
T3
原題
記憶化搜尋
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#pragma GCC optimize(10086)
#define ull unsigned long long
using namespace std;
const int N = 255;
const ull B=233;
int T,n,r;
struct ac
{
double p;ll val;
}a[N];
bool vis[N];
unordered_map <ull,map<int,double>> dp[2];
//ll dp[15][15][1<<10];
ull calc()
{
ull ans=0;
for(int i=1;i<=n;i++)
{
ll cnt=vis[i];
ans=ans*B+cnt;
}
return ans;
}
double dfs(int cnt,ull tmp,bool f)
{
if(!cnt)return 0.0;
if(dp[f][tmp][cnt])return dp[f][tmp][cnt];
double p=1,res=0.0;
for(int i=1;i<=n;i++)
{
if(vis[i])continue;
vis[i]=1;
res+=p*a[i].p*(a[i].val+dfs(cnt-1,calc(),1));
p*=(1.0-a[i].p);
vis[i]=0;
}
res+=p*dfs(cnt-1,tmp,0);
// cout<<tmp<<" "<<setprecision(6)<<fixed<<res<<endl;
return dp[f][tmp][cnt]=res;
}
int main()
{
speed();
// freopen("T3.in","r",stdin);
cin>>T;
while(T--)
{
cin>>n>>r;
memset(vis,0,sizeof vis);
memset(a,0,sizeof a);
// memset(dp,0,sizeof dp);
dp[1].clear();dp[0].clear();
for(int i=1;i<=n;i++)
{
cin>>a[i].p>>a[i].val;
}
if(!r)
{
double p=1,res=0.0;
for(int i=1;i<=n;i++)
{
if(vis[i])continue;
vis[i]=1;
res+=p*a[i].p;
p*=(1.0-a[i].p);
vis[i]=0;
}
res+=p;
cout<<0<<endl;
continue;
}
cout<<setprecision(10)<<fixed<<dfs(r,0,1)<<endl;
// break;
}
return 0;
}
/*
2
10 5
0.5000 2
0.3000 3
0.9000 1
0.5000 2
0.3000 3
0.9000 1
0.5000 2
0.3000 3
0.9000 1
0.5000 2
3 2
0.5000 2
0.3000 3
0.9000 1
*/
正解,考慮設\(g_i\)表示修第\(i\)段水管的機率,則答案為\(ans=\sum g_ival_i\)
如何求\(g_i\)呢?,設\(f_{i,j}\)表示前\(i\)段內修復了\(j\)次的機率,顯然轉移就有當前位置修或不修(既不漏)
\[f_{i,j}=(i!=j)f_{i-1,j}\times (1-p_i)^{r-j}+(j\ne 0) f_{i-1,j-1}\times (1-(1-p_i)^{r-j+1})
\]
顯然有\(g_i=\sum_{j=0}^{min{(i-1,r)}}f_{i-1,j}\times [1-(1-p_i)^{r-j}]\)注意啊邊界,因為當前必須修
注意特判\(r=0\)的時候
點選檢視程式碼
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
using namespace std;
const int N=355;
struct ac
{
double p;ll val;
}a[N];
int T,n,r;
double f[N][N],g[N],qpow[N][N];
int main()
{
speed();
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
cin>>T;
while(T--)
{
cin>>n>>r;
if(!r)
{
cout<<0.00000000<<endl;
continue;
}
memset(f,0,sizeof f);
memset(a,0,sizeof a);memset(g,0,sizeof g);
for(int i=1;i<=n;i++)
{
cin>>a[i].p>>a[i].val;
qpow[i][0]=1;
for(int j=1;j<=r;j++)qpow[i][j]=qpow[i][j-1]*(1-a[i].p);
}
// f[1][0]=pow(1-a[1].p,r);
// for(int i=2;i<=n;i++)f[i][0]=f[i-1][0]*pow(1-a[i].p,r);
f[1][0]=qpow[1][r];f[1][1]=g[1]=1.0-qpow[1][r];
for(int i=2;i<=n;i++)
{
for(int j=0;j<=min(i,r);j++)
{
f[i][j]=(i!=j)*f[i-1][j]*qpow[i][r-j]+(j!=0)*f[i-1][j-1]*(1.0-qpow[i][r-j+1]);
}
}
for(int i=2;i<=n;i++)
for(int j=0;j<=min(i-1,r);j++)
g[i]+=f[i-1][j]*(1.0-qpow[i][r-j]);
double ans=0;
for(int i=1;i<=n;i++)ans+=g[i]*a[i].val;
cout<<setprecision(10)<<fixed<<ans<<endl;
}
return 0;
}
T4
分塊,deque可以直接訪問,服了
注意越界問題
點選檢視程式碼
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
using namespace std;
const int N=1e5+5;
// #pragma GCC optimize(3)
int n,a[N],q,sq,bl[N],cnt[340][N];
int be[N],ed[N];
deque <int> dq[340];
void T()
{
cout<<"*************"<<sq<<" "<<n/sq<<" "<<endl;
for(int i=1;i<=sq;i++)
{
cout<<dq[i].size()<<endl;
for(auto s:dq[i])cout<<s<<" ";
cout<<endl;
}
cout<<endl;
}
void init()
{
for(int i=1;i<=n;i++)
{
bl[i]=(i-1)/sq+1;
be[i]=(bl[i]-1)*sq+1;
ed[i]=min(n,bl[i]*sq);
}
// for(int i=1;i<=n;i++)
// {
// cout<<be[i]<<" "<<ed[i]<<endl;
// }
for(int x=1;x<=n;x+=sq)
{
for(int i=be[x];i<=ed[x];i++)
dq[bl[x]].pb(a[i]),++cnt[bl[x]][a[i]];
}
// T();
}
int tmp[N];
void update(int l,int r)
{
if(bl[l]==bl[r])
{
int b=bl[l];
int x=dq[b][r-be[l]];
dq[b].erase(dq[b].begin()+(r-be[l]));
dq[b].insert(dq[b].begin()+(l-be[l]),x);
return;
}
// cout<<"*****&"<<endl;
dq[bl[l]].insert(dq[bl[l]].begin()+ (l-be[l]),dq[bl[r]][r-be[r]]);
// cout<<"*****"<<endl;
++cnt[bl[l]][dq[bl[r]][r-be[r]]];
--cnt[bl[r]][dq[bl[r]][r-be[r]]];
dq[bl[r]].erase(dq[bl[r]].begin()+(r-be[r]));
// cout<<"*****"<<endl;
for(int b=bl[l]+1;b<=bl[r];b++)
{
int t=dq[b-1].back();
dq[b].push_front(t);
++cnt[b][t];
dq[b-1].pop_back();
--cnt[b-1][t];
}
}
int query(int l,int r,int k)
{
int res=0;
if(bl[l]==bl[r])
{
int b=bl[l];
for(int i=l;i<=r;i++)
if(dq[b][i-be[l]]==k)res++;
return res;
}
res+=query(l,ed[l],k);
for(int b=bl[l]+1;b<=bl[r]-1;b++)
{
res+=cnt[b][k];
}
res+=query(be[r],r,k);
return res;
}
int main()
{
speed();
// freopen("in.in","r",stdin);
// freopen("fk.out","w",stdout);
cin>>n;
sq=max(3,(int)sqrt(n));
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
init();
// cout<<"********"<<endl;
cin>>q;
int op,l=0,r=0,last=0,k;
while(q--)
{
cin>>op>>l>>r;
l=(l+last-1)%n+1;
r=(r+last-1)%n+1;
if(l>r)swap(l,r);
if(op==1)
{
// cout<<"*****"<<endl;
update(l,r);
// cout<<"*****"<<endl;
}
else
{
cin>>k;
k=(k+last-1)%n+1;
last=query(l,r,k);
cout<<last<<endl;
}
}
return 0;
}