10.14 上午 考试
T1
定义 tot=n+m 假设n是较小的
那么每次操作相当于 n=n*2 m=m-(tot-m)=2*m-tot
即直接在mod n+m意义下 快速幂即可
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline int read()
{
char q=getchar();int ans=0;
while(q<'0'||q>'9')q=getchar();
while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
return ans;
}
ll qpow(ll a,ll ci,ll mod)
{
ll ans=1;
while(ci)
{
if(ci&1)
ans=ans*a%mod;
a=a*a%mod;
ci>>=1;
}
return ans;
}
int ci;
ll n,m;
int main(){
scanf("%lld%lld%d",&n,&m,&ci);
ll tt=n*qpow(2,ci,n+m)%(n+m);
cout<<min(tt,n+m-tt);
}
我在考试的时候发现了 对于每一个n、m,它们最后不是一个变成0,就是循环
然后我就用了map...
T2
直接预处理出来每一个"坏对"
这个可以通过枚举$a_i$的倍数来实现
不细讲了
我只是忘了判$a_i<=K$...
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#define INF 0x7fffffff
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline int read()
{
char q=getchar();int ans=0;
while(q<'0'||q>'9')q=getchar();
while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
return ans;
}
const int N=100006;
struct son
{
int l,r;
}ji[N*3];
int con;
int n,K;
int a[N],maxa;
int q[N];
vector<int> L[N],R[N];
void chu()
{
int order;
for(int i=1;i<=n;++i)
{
if(a[i]<=K)//鑰冭瘯娌℃墦鍟婂晩鍟婂晩
{
q[a[i]]=i;
continue;
}
order=0;
for(int j=K;j<=maxa;j+=a[i])
if(order<q[j])
order=q[j];
if(order)
{
++con;
ji[con].l=order;
ji[con].r=i;
}
q[a[i]]=i;
}
for(int i=1;i<=con;++i)
{
L[ji[i].l].push_back(ji[i].r);
R[ji[i].r].push_back(ji[i].l);
}
}
ll work()
{
ll ans=0;
int tt,mx,mn;
mx=0;
for(int i=1;i<=n;++i)
{
tt=R[i].size();
for(int j=0;j<tt;++j)
if(mx<R[i][j])
mx=R[i][j];
ans+=(i-mx);
}
/*mn=n+1;
for(int i=n;i>=1;--i)
{
tt=L[i].size();
for(int j=0;j<tt;++j)
if(mn>L[i][j])
mn=L[i][j];
ans+=(mn-i);
}
return ans/2;*/
return ans;
}
int main(){
//freopen("T2.in","r",stdin);
//freopen("T2.out","w",stdout);
n=read();K=read();
for(int i=1;i<=n;++i)
{
a[i]=read();
if(maxa<a[i])
maxa=a[i];
}
chu();
cout<<work();
}
T3
$f_{i,j}$ 前i行 第i行用恰好j种颜色的方案数
$$ f_{i,j}=(\sum_{k=1}^{a_{i-1}}f_{i-1,k})*C_m^j*g_{a_i,j} - f_{i-1,j}*g_{a_i,j} $$
其中 g_{i,j} 表示 在i个位置里用j种颜色放的方案数
$$g_{i,j}=g_{i-1,j}*(j-1)+g_{i-1,j-1}*j$$
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline int read()
{
char q=getchar();int ans=0;
while(q<'0'||q>'9')q=getchar();
while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
return ans;
}
const int N=1000006;
int prime[N],cnt;
bool he[N];
int mn[N];
int n,m,mod;
int a[N],maxa;
ll g[5006][5006];
ll C[N];
void get_g()
{
g[1][1]=1;//没有组合意义
for(int i=1;i<=maxa;++i)
for(int j=1;j<=i&&j<=m;++j)
{
g[i][j]=(g[i][j]+g[i-1][j]*(j-1)%mod)%mod;
g[i][j]=(g[i][j]+g[i-1][j-1]*j%mod)%mod;
}
/*printf("\n");
for(int i=1;i<=maxa;++i)
{
for(int j=1;j<=maxa;++j)
printf("%lld ",g[i][j]);
printf("\n");
}
printf("\n");*/
}
int t[N];
inline void jia(int x)
{
while(x!=1)
{
++t[mn[x]];
x/=prime[mn[x]];
}
}
inline void jian(int x)
{
while(x!=1)
{
--t[mn[x]];
x/=prime[mn[x]];
}
}
inline ll get_get()
{
ll ans=1;
for(int i=1;i<=cnt;++i)
if(t[i])
for(int j=1;j<=t[i];++j)
ans=ans*prime[i]%mod;
return ans;
}
void chu()
{
int q1=min(maxa,m);
for(int i=2;i<=m;++i)
{
if(!he[i])
{
prime[++cnt]=i;
mn[i]=cnt;
}
for(int j=1;j<=cnt&&prime[j]*i<=m;++j)
{
he[i*prime[j]]=1;
mn[i*prime[j]]=j;
if(i%prime[j]==0)
break;
}
}
for(int i=0;i<q1;++i)
{
jia(m-i);
jian(i+1);
C[i+1]=get_get();
//printf("%lld ",C[i+1]);
}
//printf("\n");
}
ll f[2][1000006];
ll dp()
{
int pre;
int now=0;
f[0][0]=1;
for(int i=1;i<=n;++i)
{
now^=1;pre=now^1;
for(int j=0;j<=maxa;++j)
f[now][j]=0;
//printf("now=%d pre=%d\n",now,pre);
for(int j=1;j<=a[i];++j)
f[now][j]=(f[pre][0]*C[j]%mod*g[a[i]][j]%mod-f[pre][j]*g[a[i]][j]%mod+mod)%mod;
f[now][0]=0;
for(int j=1;j<=a[i];++j)
f[now][0]=(f[now][0]+f[now][j])%mod;
}
return f[now][0]%mod;
}
int main(){
//freopen("T3.in","r",stdin);
//freopen("kalanchoe6.in","r",stdin);
n=read();m=read();mod=read();
for(int i=1;i<=n;++i)
{
a[i]=read();
if(maxa<a[i])
maxa=a[i];
}
get_g();
chu();
cout<<dp();
}
今天真是日了狗了...
第一题,想了半天以为是正解,其实是又犯了老错误
每一个简单题,我都要把它搞复杂,以后要先把原始式子写出来...
而且想到的东西要及时写下来,防止像今天第三题忘了...
以后有价值的题在写blog,太浪费时间了...