Simple Set Problem 尺取,双指针,排序
Data Generation 概率,矩阵快速幂
PSO 期望,签到
Guess 推式子,Pollard-Rho筛素数获得全部因子
Kong Ming Qi 构造
Circuit 最短路计数,弗洛伊德
a-b Problem 贪心,签到
首先将全部数字加入集合,数字记录所属集合,从小到大移动左指针,而后右指针在原来基础上向右扩展至第一个满足的即可。取一个最小值
# include
using namespace std;
typedef long long int ll;
struct node
{
int val,id;
};
struct node s[1000000+10];
int cnt[1000000+10];
bool cmp(struct node &x,struct node&y)
{
return x.val>t;
while(t--)
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cnt[i]=0;
}
int len=0;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
for(int j=1;j<=x;j++)
{
len++;
cin>>s[len].val;
s[len].id=i;
}
}
sort(s+1,s+1+len,cmp);
int ans=2e9+10;
int pos=0,nowcnt=0;
for(int i=1;i<=len;i++)
{
if(i>=2)
{
cnt[s[i-1].id]--;
if(cnt[s[i-1].id]==0)
nowcnt--;
}
while(pos<=len&&nowcnt
最终答案就是由于每个位置匹配成功的贡献是1,所以最终答案就是n-每个匹配成功的期望。
而每个位置还是相互独立的,所以可以看成n*p[0] 其中p[0]是m次交换之后次成功的期望。
当第i-1次0在自己的位置上时,p[i-1] * ( 1 + (n-1)^2 ) / ( n^2 ),即n^2种交换,只有[0,0]交换,和没有0的交换才能保证0仍然在原位置不懂。
当第i-1次0不在自己的位置上时,( 1-p[i-1] ) * ( 2/(n^2) )
二者综合,可以得出p[i]=(n-2)/n * p[i-1] + 2 / (n^2)
可以用矩阵快速幂解决,但n,m的范围很大,注意对n取模,防止相乘直接爆ll
#include
using namespace std; typedef long long int ll; # define mod 998244353 ll base[2][2],res[2][2]; void mulans() { ll temp[2][2]; for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { temp[i][j]=0; } } for(int k=0;k<2;k++) { for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { temp[i][j]=(temp[i][j]+res[i][k]*base[k][j]%mod)%mod; } } } for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { res[i][j]=temp[i][j]; } } return ; } void mulbase() { ll temp[2][2]; for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { temp[i][j]=0; } } for(int k=0;k<2;k++) { for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { temp[i][j]=(temp[i][j]+base[i][k]*base[k][j]%mod)%mod; } } } for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { base[i][j]=temp[i][j]; } } return ; } void qp(ll pow) { for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { res[i][j]=0; res[i][i]=1; } } while(pow) { if(pow&1) mulans(); pow>>=1; mulbase(); } } ll qsm(ll bas,ll pow) { ll ans=1; bas%=mod; while(pow) { if(pow&1) ans=ans*bas%mod; pow>>=1; bas=bas*bas%mod; } return ans; } int main() { int t; cin>>t; while(t--) { ll n,m; scanf("%lld%lld",&n,&m); n%=mod; for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { base[i][j]=0; } } ll now=((n-2)%mod+mod)%mod*qsm(n,mod-2)%mod; ll noww=2ll*qsm(n*n%mod,mod-2)%mod; base[0][0]=now; base[0][1]=base[1][1]=1; qp(m); ll ans=(res[0][0]+res[0][1]*noww%mod)%mod; ans*=n; ans%=mod; cout<<((n-ans)%mod+mod)%mod<<'\n'; } return 0; }
其实可以暴力打出前几十个数字的表,发现,只有当n时质数或者n是一个质数的幂的时候,s[n]才不是0
然后利用PR求解即可。
#include
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef long long ll;
using namespace std;
const int MOD=998244353;
ll ksm(ll a,ll b,ll p){
ll ret=1;
for(;b;b>>=1,a=(__int128)a*a%p)
if(b&1)ret=(__int128)ret*a%p;
return ret;
}
bool Miller_Rabin(ll p){
if(p<2)return 0;
if(p==2||p==3)return 1;
ll d=p-1,r=0;
while(!(d&1))++r,d>>=1;
for(ll k=0;k<10;++k){
ll a=rand()%(p-2)+2;
ll x=ksm(a,d,p);
if(x==1||x==p-1)continue;
for(int i=0;i1)return d;
}
}
ll d=__gcd(val,x);
if(d>1)return d;
}
}
void solve(ll x){
if(x<2)return;
if(Miller_Rabin(x)){
decom[++tot]=x;
return;
}
ll p=x;
while(p==x)p=Pollard_Rho(x);
solve(x/p);solve(p);
}
# define mod 998244353
int main(){
fastio;
srand(time(0));
int T;cin>>T;
while(T--){
tot=0;
ll n;cin>>n;
assert(1<=n&&n<=(ll)(1e18));
solve(n);
sort(decom+1,decom+tot+1);
tot=unique(decom+1,decom+tot+1)-(decom+1);
if(tot==1)
{
cout<
首先有一个构造方案,图中黑点可以消去白点三个,而自己保持不变。根据这一构造,在n>=3的时候,如果m>=3,可以先利用左侧消去将m消三列,留下最后三行的后三列没被消去,利用右侧方案,消去。最终会变成一个n<=3,m<=3的情况
首先n=1||m=1的时候,是对应行列个数除以2向上取整。
n<=3m<=3的时候可以打表出来
#include
using namespace std; typedef long long int ll; int nx[4]={0,0,-1,1}; int ny[4]={1,-1,0,0}; int a[10][10],n,m; bool check(int x,int y) { return x>=0&&x<=n+1&&y>=0&&y<=m+1; } int ans=1e9; int all; void work() { int flag=0; if(ans==1) return ; for(int i=0;i<=n+1;i++) { for(int j=0;j<=m+1;j++) { if(a[i][j]) { for(int k=0;k<4;k++) { int xx=i+nx[k]; int yy=j+ny[k]; if(check(xx,yy)&&a[xx][yy]) { int xxx=xx+nx[k]; int yyy=yy+ny[k]; if(check(xxx,yyy)&&!a[xxx][yyy]) { a[i][j]=0; a[xx][yy]=0; a[xxx][yyy]=1; work(); a[i][j]=1; a[xx][yy]=1; a[xxx][yyy]=0; flag=1; } } } } } } if(flag==0) { int nowcnt=0; for(int i=0;i<=n+1;i++) { for(int j=0;j<=m+1;j++) { nowcnt+=(a[i][j]); } } if(nowcnt >t; while(t--) { int x,y; scanf("%d%d",&x,&y); if(x>y) swap(x,y); if(x==1) { cout<<(y+1)/2<<'\n'; } else { if(x<=4&&y<=4) { cout<
有向图计环,在弗洛伊德的时候,转移点k从1枚举到n。考虑对每个环,记录包含[1,1],[1,2],[1,3]...[1,n]的全部环,对于一个包含[1,k]的环,要想不重复的记录,需要以k为起点,这样,包含[1,2]的以2为起点的环,和包含[1,3]以3为起点的环。一定不会重复。又比如,[1,7]的环中,有[4,6],[1,3]。。各种,而[4,6]的环,在[1,6]的时候,已经被以6为起点的记录。
#include
using namespace std;
typedef long long int ll;
ll dis[510][510],cnt[510][510],inf=1e15,edge[510][510];
# define mod 998244353
int main()
{
cin.tie(0);
ios::sync_with_stdio(0);
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
dis[i][j]=inf;
dis[i][i]=0;
cnt[i][j]=0;
edge[i][j]=0;
}
}
while(m--)
{
int x,y;
ll val;
cin>>x>>y>>val;
dis[x][y]=min(dis[x][y],val);
edge[x][y]=val;
cnt[x][y]=1;
}
ll minn=1e18,ans=0;
for(int k=1; k<=n; k++)
{
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(dis[i][j]==dis[i][k]+dis[k][j])
{
cnt[i][j]=(cnt[i][j]+cnt[i][k]*cnt[k][j]%mod)%mod;
}
else if(dis[i][j]>dis[i][k]+dis[k][j])
{
dis[i][j]=dis[i][k]+dis[k][j];
cnt[i][j]=cnt[i][k]*cnt[k][j]%mod;
}
}
}
for(int i=1; i=inf)
{
cout<<-1<<" "<<-1<<'\n';
continue;
}
cout<
按照A+B排序的原理是,A+B如果大,要么可以让自己加的分多,要么可以避免对面加更多的分。
# include
using namespace std;
typedef long long int ll;
struct node
{
int a,b,c;
};
struct node s[100000+10];
bool cmp(struct node &x, struct node &y)
{
return x.c>y.c;
}
int main()
{
cin.tie(0);
ios::sync_with_stdio(0);
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s[i].a>>s[i].b;
s[i].c=s[i].a+s[i].b;
}
sort(s+1,s+1+n,cmp);
ll sum1=0,sum2=0;
for(int i=1;i<=n;i++)
{
if(i%2)
{
sum1+=s[i].a;
}
else
{
sum2+=s[i].b;
}
}
cout<