dp[i]表示前i个的期望是多少,第i个失败的话就是dp[i]=dp(i-1)*(100-p[i]),成功的话就要去枚举起点,所以方程就是
- #include
- #define ll long long
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- const ll MAX=1e6+5;
- const int mod=1e9+7;
- ll n,m,p[1005],dp[1005],mul[1005][1005];
- ll 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;
- }
- int main(){
- ll inv=qpow(100,mod-2);
- cin>>n>>m;
- for(int i=1;i<=n;i++) cin>>p[i],mul[i][i]=p[i]*inv%mod;
- for(int i=1;i<=n;i++)
- for(int j=i+1;j<=n;j++)
- mul[i][j]=(mul[i][j-1]*p[j]%mod)*inv%mod;
- for(int i=1;i<=n;i++){
- dp[i]=(dp[i-1]*(100-p[i])%mod)*inv%mod;
- for(int j=1;j<=i;j++){
- dp[i]=(dp[i]+(((qpow(i-j+1,m)+dp[j-2])%mod)*((100-p[j-1])*inv%mod)%mod)*mul[j][i]%mod)%mod;
- }
- }
- printf("%lld\n",dp[n]);
- system("pause");
- return 0;
- }
其实是和二进制差不多的,但是3进制会有2这个余数,而题目中又说不能有重复的,所以碰到2的话比该位高的最近的0改为1,其后全改为0就可以啦
- #include
- #define ll long long
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- const ll MAX=1e6+5;
- const int mod=1e9+7;
- ll q,n,fac[66],vis[66];
- ll qpow(ll a,ll b){
- ll res=1;
- while(b){
- if(b&1) res=res*a;
- a=a*a;
- b>>=1;
- }
- return res;
- }
- int main(){
- fac[0]=1;
- for(int i=1;i<=39;i++) fac[i]=fac[i-1]*3LL;
- cin>>q;
- while(q--){
- cin>>n;
- for(int i=0;i<=40;i++) vis[i]=0;
- ll sup=upper_bound(fac,fac+39,n)-fac;
- ll x=sup-1,y=n;
- while(y){
- while(x>=0&&y
- if(x<0) break;
- vis[x]=y/fac[x];
- y%=fac[x];
- }
- ll zero;
- for(int i=sup;i>=0;i--){
- //cout<
- if(vis[i]==0) zero=i;
- if(vis[i]>1){
- vis[zero]=1;
- for(int j=zero-1;j>=0;j--) vis[j]=0;
- break;
- }
- }
- ll ans=0;
- for(int i=0;i<=sup;i++)
- if(vis[i]) ans+=fac[i];
- printf("%lld\n",ans);
- }
- system("pause");
- return 0;
- }
1458A - Row GCD gcd的性质
gcd的一条性质关于辗转相除法的:gcd(a,b)=gcd(a,b-a),gcd(a,b,c)=gcd(a,b-a,c-b);
所以该题gcd(a[1]+b[j],a[2]+b[j],a[3]+b[j])=gcd(a[1]+b[j],a[2]-a[1],a[3]-a[2]);
1459C. Row GCD(经典数论)_a碟的博客-CSDN博客
- #include
- #define ll long long
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- const ll MAX=1e6+5;
- const int mod=1e9+7;
- ll n,m,a[200005],b[200005];
- int main(){
- cin>>n>>m;
- ll q=0;
- for(int i=1;i<=n;i++){
- cin>>a[i];
- }
- q=a[2]-a[1];
- for(int i=3;i<=n;i++) q=__gcd(q,abs(a[i]-a[i-1]));
- for(int i=1;i<=m;i++){
- cin>>b[i];
- if(n==1){
- printf("%lld\n",a[1]+b[i]);continue;
- }
- printf("%lld ",__gcd(a[1]+b[i],q));
- }
- system("pause");
- return 0;
- }
C-公因子_牛客练习赛66 (nowcoder.com)gcd的性质
也上一题类似,用的是一个性质,这次只要关注a[1]的取值就行了,但貌似只有排完序求得x的最小值是正确的
Row GCD(差分+辗转相减法)_一个石马农的博客-CSDN博客
- #include
- #define ll long long
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- const ll MAX=1e6+5;
- const int mod=1e9+7;
- ll n,a[1000006];
- int main(){
- cin>>n;
- for(int i=1;i<=n;i++) cin>>a[i];
- sort(a+1,a+n+1);
- ll g=abs(a[2]-a[1]);
- for(int i=3;i<=n;i++) g=__gcd(g,abs(a[i]-a[i-1]));
- if(a[1]>=0) printf("%lld %lld\n",g,g-a[1]%g);
- else printf("%lld %lld\n",g,abs(a[1])%g);
- system("pause");
- return 0;
- }
4302 Interval GCD (zzstep.com)线段树,树状数组,gcd的性质
也是用到了上面的那条性质,线段树维护a数组的差分数组的gcd,这样每次修改一个区间[x,y]只需要修改x,和y+1就行,树状数组维护差分数组的前缀和方便求答案
Interval GCD(线段树区间增加、区间查询)_sunday_soft的博客-CSDN博客
- #include
- #define ll long long
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- const ll MAX=1e6+5;
- const int mod=1e9+7;
- ll n,m,a[500005],b[500005],t[500005<<2],ta[5000005];
- void pushup(ll p){t[p]=__gcd(t[p<<1],t[p<<1|1]);}
- void build(ll l,ll r,ll p){
- if(l==r){t[p]=b[l];return;}
- ll mid=l+r>>1;
- build(l,mid,p<<1);
- build(mid+1,r,p<<1|1);
- pushup(p);
- }
- void update(ll l,ll r,ll x,ll y,ll p){
- if(l==r){t[p]+=y;return;}
- ll mid=l+r>>1;
- if(x<=mid) update(l,mid,x,y,p<<1);
- else update(mid+1,r,x,y,p<<1|1);
- pushup(p);
- }
- ll query(ll l,ll r,ll L,ll R,ll p){
- if(L<=l&&r<=R) return abs(t[p]);
- ll mid=l+r>>1;
- ll val=0;
- if(L<=mid) val=__gcd(val,query(l,mid,L,R,p<<1));
- if(R>mid) val=__gcd(val,query(mid+1,r,L,R,p<<1|1));
- return abs(val);
- }
- void add(ll x,ll y){
- for(int i=x;i<=n;i+=lowbit(i))
- ta[i]+=y;
- }
- ll ask(ll x){
- ll res=0;
- for(int i=x;i;i-=lowbit(i))
- res+=ta[i];
- return res;
- }
- int main(){
- scanf("%lld%lld",&n,&m);
- for(int i=1;i<=n;i++) scanf("%lld",&a[i]),b[i]=a[i]-a[i-1];
- build(1,n,1);
- while(m--){
- char op;
- ll x,y,z;;
- cin>>op;
- if(op=='Q'){
- scanf("%lld%lld",&x,&y);
- ll val=a[x]+ask(x);
- printf("%lld\n",__gcd(val,query(1,n,x+1,y,1)));
- }
- else{
- scanf("%lld%lld%lld",&x,&y,&z);
- update(1,n,x,z,1),add(x,z);
- if(y
update(1,n,y+1,-z,1),add(y+1,-z); - }
- }
- system("pause");
- return 0;
- }
1444A - Division
p不整除q直接输出p,否则枚举q的质因子,p一直除这个质因子知道p不能整除q,更新最大值
Codeforces Round #680 (Div. 2, based on Moscow Team Olympiad)——C. Division_cll7777777的博客-CSDN博客
- #include
- #define ll long long
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- const ll MAX=1e6+5;
- const int mod=1e9+7;
- ll q,p,t,cnt;
- ll pri[1000006],a[1000006],vis[1000006];
- bool ispri[1000006];
- void prime(ll n){
- memset(ispri,1,sizeof(ispri));
- ispri[0]=ispri[1]=0;
- for(ll i=2;i<=n;i++){
- if(ispri[i]) pri[++cnt]=i;
- for(int j=1;j<=cnt&&i*pri[j]<=n;j++){
- ispri[i*pri[j]]=0;
- if(i%pri[j]==0) break;
- }
- }
- }
- int main(){
- prime(1000000);
- scanf("%lld",&t);
- while(t--){
- scanf("%lld%lld",&p,&q);
- ll y=q,ct=0;
- if(p%q){printf("%lld\n",p);continue;}
- for(int i=1;i<=cnt;i++){
- if(q%pri[i]==0){
- a[++ct]=pri[i];
- while(q%pri[i]==0) q/=pri[i];
- }
- }
- if(q>1) a[++ct]=q;
- ll x=p,ans=0;
- for(int i=1;i<=ct;i++){
- x=p;
- while(x%y==0&&x%a[i]==0) x/=a[i];
- ans=max(x,ans);
- }
- printf("%lld\n",ans);
- }
- system("pause");
- return 0;
- }
1551C - Interesting Story
一共就5个字母,枚举一下如果当前字母的个数大于其他所有个数最多可以用几个单词,枚举的时候如果是当前字母就加1,不是就减1,最后看看能加几个单词
- #include
- #define ll long long
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- const ll MAX=1e6+5;
- const int mod=1e9+7;
- ll t,n,a[200005];
- string s[200005];
- int main(){
- scanf("%lld",&t);
- while(t--){
- scanf("%lld",&n);
- ll ans=0;
- for(int i=1;i<=n;i++) cin>>s[i];
- for(char c='a';c<='e';c++){
- for(int i=1;i<=n;i++) a[i]=0;
- for(int i=1;i<=n;i++)
- for(int j=0;j
size();j++) - if(s[i][j]==c) a[i]++;
- else a[i]--;
- sort(a+1,a+n+1);
- ll res=0,sum=0;
- for(int i=n;i>=1;i--){
- sum+=a[i];
- if(sum<=0) break;
- res++;
- }
- ans=max(ans,res);
- }
- printf("%lld\n",ans);
- }
- system("pause");
- return 0;
- }
A-Game_第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(上海)(热身赛) 期望
期望的线性性,E(x+y)=E(x)+E(y), 如果每次都是互质的话只需要抽n/2次就够了,只抽一次的话是1/C(n,2),预处理出符合条件的对数cnt,答案就是cnt/C(n,2)*n/2,注意n的奇偶需要判断一下,奇数的话是(n-1)/2次,虽然说计算机的出发两者其实是一样的,但是放到期望里面好像就不一样了
北化ACM集训队-浅谈期望题的做法_哔哩哔哩_bilibili
- #include
- #define ll long long
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- const ll MAX=1e6+5;
- const int mod=1e9+7;
- ll n;
- int main(){
- ll cnt=0;
- scanf("%lld",&n);
- for(int i=1;i<=n;i++)
- for(int j=i+1;j<=n;j++)
- if(__gcd(i,j)==1) cnt++;
- ll p=cnt,q=n-1;
- if(n&1) q=n;
- printf("%lld/%lld\n",p/__gcd(p,q),q/__gcd(p,q));
- system("pause");
- return 0;
- }
570D - Tree Requests树上启发式合并
和板子是一样的套路,看来启发式合并或许难的不是合并的过程,而是先要想出一个可以适合启发式合并的暴力思路,这个题就是没有想到暴力的思路,其实也就是统计每个深度的各个颜色的个数,然后离线判断每个询问,板子大致一样,也就是统计函数要根据题目来写
题解 CF570D 【Tree Requests】 - 牛蛙丶丶 的幼儿园 - 洛谷博客
- #include
- #define ll long long
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- const ll MAX=1e6+5;
- const int mod=1e9+7;
- ll n,m,tot[500005][27];
- ll son[500005],siz[500005],dep[500005],fson,vis[500005];
- bool ans[500005];
- char s[500005];
- struct qq{
- ll su,id;
- };
- vector
q[500005]; - ll head[1000006],cnt;
- struct Edge{
- ll from,to,next;
- }edge[1000006];
- void addedge(ll from, ll to){
- edge[++cnt].from=from;
- edge[cnt].to=to;
- edge[cnt].next=head[from];
- head[from]=cnt;
- }
- void dfs1(ll u,ll fa){
- dep[u]=dep[fa]+1;siz[u]=1;
- for(int i=head[u];i;i=edge[i].next){
- ll j=edge[i].to;
- if(j==fa) continue;
- dfs1(j,u);
- siz[u]+=siz[j];
- if(siz[j]>siz[son[u]]) son[u]=j;
- }
- }
- void cal(ll u,ll fa,ll val){
- tot[dep[u]][s[u]-'a']+=val;
- for(int i=head[u];i;i=edge[i].next){
- ll j=edge[i].to;
- //if(j!=fa&&j!=fson) cal(j,u,val);
- if(j!=fa&&!vis[j]) cal(j,u,val);
- }
- }
- bool check(ll u){
- ll res=0;
- for(int i=0;i<26;i++){
- if(tot[u][i]&1) res++;
- if(res>1) return 0;
- }
- return 1;
- }
- void dfs2(ll u,ll fa,ll keep){
- for(int i=head[u];i;i=edge[i].next){
- ll j=edge[i].to;
- if(j!=fa&&j!=son[u]) dfs2(j,u,0);
- }
- if(son[u]) dfs2(son[u],u,1),vis[son[u]]=1;
- cal(u,fa,1);vis[son[u]]=0;
- for(int i=0;i
size();i++) ans[q[u][i].id]=check(q[u][i].su);
- if(!keep) cal(u,fa,-1);
- }
- int main(){
- scanf("%lld%lld",&n,&m);
- for(int i=2;i<=n;i++){
- ll u;scanf("%lld",&u);
- addedge(u,i);addedge(i,u);
- }
- scanf("%s",s+1);
- dfs1(1,0);
- for(int i=1;i<=m;i++){
- ll a,b;
- scanf("%lld%lld",&a,&b);
- q[a].push_back({b,i});
- }
- dfs2(1,0,1);
- for(int i=1;i<=m;i++)
- if(ans[i]) printf("Yes\n");
- else printf("No\n");
- system("pause");
- return 0;
- }
CF208E Blood Cousins -树上启发式合并
新学了个倍增求k级祖先,下面的人讲的还可以,lg[i]就是log2(i)+1,应该就是表示i可以向上跳几次
题解 P3379 【【模板】最近公共祖先(LCA)】 - MorsLin 的博客 - 洛谷博客
找出k级祖先来然后去遍历这个祖先的子树,相同深度的个数减1就是答案,注意这是个森林,所以每个根就要进行dfs
题解 CF208E 【Blood Cousins】 - 坡道旁的向日葵 - 洛谷博客
- #include
- #define ll long long
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- const ll MAX=1e6+5;
- const int mod=1e9+7;
- ll n,m,tot[500005];
- ll son[500005],siz[500005],dep[500005],fson;
- ll f[100005][30],lg[100005],ans[100005];
- struct qq{
- ll su,id;
- };
- vector
q[500005]; - ll head[1000006],cnt;
- struct Edge{
- ll from,to,next;
- }edge[1000006];
- void addedge(ll from, ll to){
- edge[++cnt].from=from;
- edge[cnt].to=to;
- edge[cnt].next=head[from];
- head[from]=cnt;
- }
- ll kthparent(ll u,ll k){
- for(int i=lg[dep[u]];i>=0;i--)
- if(dep[u]-dep[f[u][i]]<=k) k-=dep[u]-dep[f[u][i]],u=f[u][i];
- return u;
- }
- void dfs1(ll u,ll fa){
- dep[u]=dep[fa]+1;siz[u]=1;
- for(int i=1;i<=lg[dep[u]];i++)
- f[u][i]=f[f[u][i-1]][i-1];
- for(int i=head[u];i;i=edge[i].next){
- ll j=edge[i].to;
- if(j==fa) continue;
- dfs1(j,u);
- siz[u]+=siz[j];
- if(siz[j]>siz[son[u]]) son[u]=j;
- }
- }
- void cal(ll u,ll fa,ll val){
- tot[dep[u]]+=val;
- for(int i=head[u];i;i=edge[i].next){
- ll j=edge[i].to;
- //if(j!=fa&&j!=fson) cal(j,u,val);
- if(j!=fa&&j!=fson) cal(j,u,val);
- }
- }
- void dfs2(ll u,ll fa,ll keep){
- for(int i=head[u];i;i=edge[i].next){
- ll j=edge[i].to;
- if(j!=fa&&j!=son[u]) dfs2(j,u,0);
- }
- if(son[u]) dfs2(son[u],u,1),fson=son[u];
- cal(u,fa,1);fson=0;
- for(int i=0;i
size();i++) ans[q[u][i].id]=tot[dep[q[u][i].su]]-1;
- if(!keep) cal(u,fa,-1);
- }
- int main(){
- lg[0]=-1;
- for(int i=1;i<=100000;i++) lg[i]=lg[i>>1]+1;
- scanf("%lld",&n);
- for(int i=1;i<=n;i++){
- scanf("%lld",&f[i][0]);
- if(f[i][0]) addedge(f[i][0],i),addedge(i,f[i][0]);
- }
- for(int i=1;i<=n;i++){
- if(!f[i][0]) dfs1(i,0);
- }
- scanf("%lld",&m);
- for(int i=1;i<=m;i++){
- ll x,p;
- scanf("%lld%lld",&x,&p);
- q[kthparent(x,p)].push_back(qq{x,i});
- }
- for(int i=1;i<=n;i++){
- if(!f[i][0]) dfs2(i,0,0);
- }
- for(int i=1;i<=m;i++) printf("%lld ",ans[i]);
- system("pause");
- return 0;
- }