1305C - Kuroni and Impossible Calculation 抽屉原理
推了三页式子还没有推出来之后去看题解直接绷不住了,一看抽屉原理就直接裂开了,确实,m只有1000,如果n>m的话那么一定有两个数是同余的那么这两个数会产生一个0,所以答案就是0,所以只需要管n<=m的情况即可,也就1000*1000的复杂度
C. Kuroni and Impossible Calculation(抽屉原理)_zjj0624的博客-CSDN博客
#include <bits/stdc++.h>
#define ll long long
#define lowbit(i) (i)&(-i)
using namespace std;
const int mod=1e9+7;
const ll inf=1e18;
const double eps=1e-8;
int qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
ll n,m,a[200005];
int main(){
scanf("%lld%lld",&n,&m);
if(n>m){
printf("0\n");
return 0;
}
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
ll ans=1;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
ans=ans*abs(a[i]-a[j])%m;
printf("%lld\n",ans);
return 0;
}
1503A - Balance the Bits 构造
右括号一定是要小于等于左括号的,s[i]=1的时候不会影响ab中左右括号的差,但是0会影响,为了修复这个影响必然还需要一个0才可以,所以0的个数要是偶数才行,这样前一半的1都为'('后一半是')',然后s[i]==0时交替放就可以,比如奇数时a[i]='(',b[i]=')',偶数时再反过来就可以了
codeforces1503A. Balance the Bits_二分抄代码的博客-CSDN博客
#include <bits/stdc++.h>
#define ll long long
#define lowbit(i) (i)&(-i)
using namespace std;
const int mod=1e9+7;
const ll inf=1e18;
const double eps=1e-8;
int qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
ll t,n,a1[200005],a0[200005];
char s[200005],aa[200005],bb[200005];
int main(){
scanf("%lld",&t);
while(t--){
scanf("%lld%s",&n,s+1);
if(s[1]!='1'||s[n]!='1'){printf("NO\n");continue;}
ll id1=0,id0=0;
for(int i=1;i<=n;i++)
if(s[i]=='0') a0[++id0]=i;
else a1[++id1]=i;
if(id0&1){printf("NO\n");continue;}
for(int i=1;i<=id1;i++){
if(i<=id1/2) aa[a1[i]]='(',bb[a1[i]]='(';
else aa[a1[i]]=')',bb[a1[i]]=')';
}
for(int i=1;i<=id0;i++){
if(i&1) aa[a0[i]]='(',bb[a0[i]]=')';
else aa[a0[i]]=')',bb[a0[i]]='(';
}
printf("YES\n");
for(int i=1;i<=n;i++) printf("%c",aa[i]);
printf("\n");
for(int i=1;i<=n;i++) printf("%c",bb[i]);
printf("\n");
}
return 0;
}
1295C - Obtain The String
把每个字母的下标都存到vector中,遍历t数组如果t[i]的vector有值且有大于ind(记录遍历的最小坐标)的值那就更新ind,否则ind=t[i]vector的最小值重新开始
#include <bits/stdc++.h>
#define ll long long
#define lowbit(i) (i)&(-i)
using namespace std;
const int mod=1e9+7;
const ll inf=1e18;
const double eps=1e-8;
int qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
ll T,a[30];
vector<ll>v[30];
char s[100005],t[100005];
int main(){
scanf("%lld",&T);
while(T--){
scanf("%s%s",s+1,t+1);
ll n=strlen(s+1),m=strlen(t+1);
for(int i=0;i<26;i++) v[i].clear(),a[i]=0;
for(int i=1;i<=n;i++)
v[s[i]-'a'].push_back(i);
ll ans=1,ind=0;
for(int i=1;i<=m;i++){
if(v[t[i]-'a'].size()>a[t[i]-'a']){
ll id=upper_bound(v[t[i]-'a'].begin(),v[t[i]-'a'].end(),ind)-v[t[i]-'a'].begin();
//ll res=v[t[i]-'a'][a[t[i]-'a']];
//cout<<res<<" "<<ind<<" "<<a[t[i]-'a']<<" "<<v[t[i]-'a'][a[t[i]-'a']]<<" "<<t[i]<<endl;
//a[t[i]-'a']++;
if(id!=v[t[i]-'a'].size()){ind=v[t[i]-'a'][id];}
else{
// cout<<res<<" "<<ind<<" "<<a['s'-'a']<<endl;
ans++;ind=v[t[i]-'a'][0];
// for(int j=0;j<26;j++) a[j]=0;
//a[t[i]-'a']=1;
}
}
else{
if(v[t[i]-'a'].size()<=0){ans=-1;break;}
//cout<<ind<<endl;
ans++;ind=v[t[i]-'a'][0];
//for(int j=0;j<26;j++) a[j]=0;
//a[t[i]-'a']=1;
}
}
printf("%lld\n",ans);
}
return 0;
}
446A - DZY Loves Sequences
这题看数据瞎搞过的,,,
求出差分数组b和b[i]的坐标c[b[i]],答案一定是在c[b[i-1]]到c[b[i+1]]-1的这段距离中,也有可能是c[b[i-1]]到c[b[i]]-1或者是c[b[i]]到c[b[i+1]]-1的这段距离中,注意下细节和满足条件就可以了
#include <bits/stdc++.h>
#define ll long long
#define lowbit(i) (i)&(-i)
using namespace std;
const int mod=1e9+7;
const ll inf=1e18;
const double eps=1e-8;
int qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
ll n,a[100005],c[100005],b[100005];
int main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),b[i]=a[i]-a[i-1];
ll cnt=0,ans=1;
for(int i=1;i<=n;i++)
if(b[i]<=0) c[++cnt]=i;
c[0]=1;c[cnt+1]=n+1;b[n+1]=1e9;
if(cnt==0){
printf("%lld\n",n);
return 0;
}
for(int i=1;i<=cnt;i++){
//cout<<c[i]<<endl;
if(c[i]==2&&b[c[i]+1]>0){ans=max(ans,c[i+1]-c[i-1]);continue;}
if(a[c[i]-1]<a[c[i]+1]-1||c[i]>2&&a[c[i]-2]<a[c[i]]-1){ans=max(ans,c[i+1]-c[i-1]);}
else ans=max(ans,max(c[i]-c[i-1]+1,c[i+1]-c[i]+1));
}
printf("%lld\n",ans);
return 0;
}
其实这题最好的方法是dp
l[i]为以i结尾可以构造的最长序列,r[i]是以i开头可以构造的最长序列,
ans=max(ans,l[i-1]+1,r[i+1]+1,l[i-1]+1+r[i+1]);
#include <bits/stdc++.h>
#define ll long long
#define lowbit(i) (i)&(-i)
using namespace std;
const int mod=1e9+7;
const ll inf=1e18;
const double eps=1e-8;
int qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
ll n,a[100005],l[100005],r[100005];
int main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
l[1]=r[n]=1;
for(int i=2;i<=n;i++)
if(a[i]>a[i-1]) l[i]=l[i-1]+1;
else l[i]=1;
for(int i=n-1;i>=1;i--)
if(a[i]<a[i+1]) r[i]=r[i+1]+1;
else r[i]=1;
ll ans=1;
for(int i=1;i<=n;i++){
ans=max({ans,l[i-1]+1,r[i+1]+1});
if(a[i-1]<a[i+1]-1) ans=max(ans,l[i-1]+1+r[i+1]);
}
printf("%lld\n",ans);
return 0;
}
Aeroplane chess - HDU 4405 - Virtual Judge (vjudge.net) 概率dp
首先如果第i个格子和第j个格子是有线连着的(i<j),那么第i个格子的期望就等于第j个格子的期望,否则就是i+1,i+2,,,i+6转移到i
【原创】概率DP总结 by kuangbin - kuangbin - 博客园 (cnblogs.com)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iomanip>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<list>
#include<stack>
#include<set>
#include<ctime>
//HDU火车头
//#include <bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-x))
using namespace std;
const int mod=1e9+7;
const ll inf=1e18;
const double eps=1e-8;
int qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
ll n,m;
ll vis[100005];
double dp[100005];
vector<ll>v[100005];
int main(){
while(scanf("%lld%lld",&n,&m)){
if(n==0&&m==0) break;
for(int i=1;i<=n;i++) v[i].clear();
for(int i=0;i<=n;i++) dp[i]=0;
for(int i=0;i<=n;i++) vis[i]=0;
for(int i=1;i<=m;i++){
ll u,vv;
scanf("%lld%lld",&u,&vv);
v[vv].push_back(u);
}
for(int i=0;i<v[n].size();i++){
ll j=v[n][i];
dp[j]=0;
vis[j]=1;
}
dp[n]=0;
for(int i=n-1;i>=0;i--){
if(!vis[i]){
for(int j=1;j<=6;j++)
if(i+j<=n) dp[i]+=dp[i+j]*1.0/6;
dp[i]+=1;
}
for(int j=0;j<v[i].size();j++){
ll k=v[i][j];
if(!vis[k]){dp[k]=dp[i];vis[k]=1;}
}
}
printf("%.4f\n",dp[0]);
}
return 0;
}
Maze - HDU 4035 - Virtual Judge (vjudge.net) 概率dp
首先要推出节点的公式来
叶子节点:
E[i] = ki*E[1] + ei*0 + (1-ki-ei)*(E[father[i]] + 1);
非叶子节点:
E[i] = ki*E[1] + ei*0 + (1-ki-ei)/m*( E[father[i]]+1 + ∑( E[child[i]]+1 ) );
之后让
E[i] = Ai*E[1] + Bi*E[father[i]] + Ci;
然后求出A[i],B[i],C[i]的表达式来,之后E[1]就是答案
【原创】概率DP总结 by kuangbin - kuangbin - 博客园 (cnblogs.com)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iomanip>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<list>
#include<stack>
#include<set>
#include<ctime>
//HDU火车头
//#include <bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-x))
using namespace std;
const int mod=1e9+7;
const ll inf=1e18;
const double eps=1e-9;
int qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
ll t,n;
double a[10005],b[10005],c[10005],k[10005],e[10005];
vector<ll>v[10005];
bool dfs(ll u,ll fa){
ll m=v[u].size();
a[u]=k[u];
b[u]=(1-k[u]-e[u])/m;
c[u]=1-k[u]-e[u];
double tmp=0;
for(int i=0;i<m;i++){
ll j=v[u][i];
if(j==fa) continue;
if(!dfs(j,u)) return 0;
a[u]+=(1-k[u]-e[u])/m*a[j];
c[u]+=(1-k[u]-e[u])/m*c[j];
tmp+=(1-k[u]-e[u])/m*b[j];
}
if(fabs(tmp-1)<eps) return 0;
a[u]/=(1-tmp);
b[u]/=(1-tmp);
c[u]/=(1-tmp);
return 1;
}
int main(){
scanf("%lld",&t);
ll cnt=0;
while(t--){
scanf("%lld",&n);
for(int i=1;i<=n;i++) v[i].clear();
for(int i=1;i<n;i++){
ll u,vv;
scanf("%lld%lld",&u,&vv);
v[u].push_back(vv);
v[vv].push_back(u);
}
for(int i=1;i<=n;i++){
scanf("%lf%lf",&k[i],&e[i]);
k[i]/=100;e[i]/=100;
}
printf("Case %d: ",++cnt);
if(dfs(1,-1)&&fabs(1-a[1])>eps){
printf("%.6lf\n",c[1]/(1-a[1]));
}
else printf("impossible\n");
}
return 0;
}