zoukankan      html  css  js  c++  java
  • 2016 ACM/ICPC Asia Regional Dalian Online

    自己还是太菜,补题离不开题解。。。

    但还是留个博客,万一以后忘了。。。

    1001 Different Circle Permutation

    Polya定理,第一次遇见,学习了一下。不旋转的时候可以得到 f[i]=f[i-1]+f[i-2] 斐波那契数列,旋转后就可以通过burnside引理求解,循环节为 gcd(i,n)。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const LL mod=1e9+7;
     5 LL pow_mod(LL a,LL n){
     6     LL res=1,t=a%mod;
     7     while(n){
     8         if(n&1) res=(res*t)%mod;
     9         t=(t*t)%mod;
    10         n/=2;
    11     }
    12     return res;
    13 }
    14 struct Mat{
    15     LL a[2][2];
    16     void init(){
    17         a[0][0]=1;
    18         a[1][0]=a[0][1]=1;
    19         a[1][1]=0;
    20     }
    21 };
    22 Mat operator *(Mat a,Mat b){
    23     Mat c;
    24     for(LL i=0;i<2;i++)
    25     for(LL j=0;j<2;j++){
    26         c.a[i][j]=0;
    27         for(LL k=0;k<2;k++)
    28             c.a[i][j]+=a.a[i][k]*b.a[k][j];
    29             c.a[i][j]%=mod;
    30     }
    31     return c;
    32 }
    33 Mat operator ^(Mat p,LL k){
    34     Mat ans; ans.init();
    35     while(k){
    36         if(k&1)
    37             ans=ans*p;
    38         k/=2;
    39         p=p*p;
    40     }
    41     return ans;
    42 }
    43 LL fun(LL x){
    44     Mat a; a.init();
    45     Mat b;
    46     b.a[0][0]=1;
    47     b.a[0][1]=0;
    48     b.a[1][0]=2;
    49     b.a[1][1]=0;
    50     a=a^(x-2);
    51     if(x>1) b=a*b;
    52     return b.a[0][0];
    53 }
    54 LL n;
    55 LL euler(LL n){
    56     LL ans=n;
    57     for(LL i=2;i*i<=n;i++){
    58         if(n%i==0){
    59             ans-=ans/i;
    60             while(n%i==0) n/=i;
    61         }
    62     }
    63     if(n>1) ans-=ans/n;
    64     return ans;
    65 }
    66 int main(){
    67     while(~scanf("%lld",&n)){
    68         if(n==1){
    69             printf("%lld
    ",2);
    70             continue;
    71         }
    72         LL ans=0;
    73         for(LL i=1;i*i<=n;i++){
    74             if(n%i==0){
    75                 ans+=fun(i)*euler(n/i)%mod;
    76                 if(n/i!=i) ans+=fun(n/i)*euler(i)%mod;
    77                 ans%=mod;
    78             }
    79         }
    80         ans=ans*pow_mod(n,mod-2)%mod;
    81         printf("%lld
    ",ans);
    82     }
    83 
    84     return 0;
    85 }
    Psong

    1002 Different GCD Subarray Query

    查询区间内不同gcd个数,区间gcd可以ST表打出,并提前二分处理出每个点向右gcd下降的地方。查询作为点对,以右端点大小排序,然后用树状数组处理。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 int n,q;
      5 int k[100005];
      6 
      7 int kk;
      8 struct node{
      9     int l,r,pos;
     10 } a[100005];
     11 bool cmp(node x,node y){
     12     return x.r<y.r;
     13 }
     14 
     15 int gcd(int x,int y){
     16     return y==0?x:gcd(y,x%y);
     17 }
     18 
     19 int lg[100005];
     20 int dp[100005][35];
     21 int RMQ_ST(int n){
     22     for(int i=1;i<=n;i++) lg[i]=(int)( log(1.0*i)/log(2.0) );
     23     for(int i=1;i<=n;i++) dp[i][0]=k[i];
     24     for(int j=1;(1<<j)<=n;j++){
     25         for(int i=1;i<=n-(1<<j)+1;i++){
     26             dp[i][j]=gcd( dp[i][j-1],dp[i+(1<<(j-1))][j-1] );
     27         }
     28     }
     29 }
     30 int find_gcd(int l,int r){
     31     int k=lg[r-l+1];
     32     return gcd(dp[l][k],dp[r-(1<<k)+1][k]);
     33 }
     34 
     35 int ans[100005];
     36 int c[100006];
     37 vector<int> vr[100005];
     38 
     39 int lowbit(int x){
     40     return x&(-x);
     41 }
     42 int add(int pos,int val){
     43     for(int i=pos;i<=n;i+=lowbit(i)){
     44         c[i]+=val;
     45     }
     46 }
     47 int sum(int pos){
     48     int res=0;
     49     for(int i=pos;i>0;i-=lowbit(i)){
     50         res+=c[i];
     51     }
     52     return res;
     53 }
     54 
     55 void init(){
     56     for(int i=1;i<=n;i++){
     57         vr[i].push_back(i);
     58         int tmp=k[i];
     59         int l=1,r=i;
     60         while(l<r){
     61             int L=l,R=r,flag=0;
     62             while(L<R){
     63                 int mid=(L+R+1)/2;
     64                 if(find_gcd(mid,i)<tmp) L=mid;
     65                 else if(find_gcd(l,i)<tmp) R=mid-1;
     66                 else { flag=1;break; }
     67             }
     68             if(!flag){
     69                 tmp=find_gcd(R,i);
     70                 vr[i].push_back(R);
     71             }
     72             else break;
     73             r=R;
     74         }
     75     }
     76 }
     77 int pos[1000006];
     78 void solve(){
     79     int R=0;
     80     for(int i=1;i<=q;i++){
     81         while(R<a[i].r){
     82             R++;
     83             for(int j=0;j<vr[R].size();j++){
     84                 int ll=vr[R][j];
     85                 int _gcd=find_gcd(ll,R);
     86                 if(pos[_gcd]==0) add(ll,1);
     87                 else if(pos[_gcd]<ll) add(ll,1),add(pos[_gcd],-1);
     88                 pos[_gcd]=max(pos[_gcd],ll);
     89             }
     90         }
     91         ans[a[i].pos]=sum(a[i].r)-sum(a[i].l-1);
     92     }
     93 }
     94 
     95 int main(){
     96     while(scanf("%d%d",&n,&q)!=EOF){
     97         for(int i=1;i<=n;i++) scanf("%d",&k[i]);
     98         RMQ_ST(n);
     99         init();
    100         kk=sqrt(n);
    101         for(int i=1;i<=q;i++){
    102             scanf("%d%d",&a[i].l,&a[i].r);
    103             a[i].pos=i;
    104         }
    105         sort(a+1,a+1+q,cmp);
    106         memset(c,0,sizeof(c));
    107         memset(pos,0,sizeof(pos));
    108         //cout<<sum(1)<<endl;
    109         solve();
    110         for(int i=1;i<=q;i++) printf("%d
    ",ans[i]);
    111     }
    112 
    113 
    114     return 0;
    115 }
    116 /*
    117 9 10
    118 3 3 4 4 4 6 6 6 9
    119 */
    Psong

    1003 Alice's Adventure in Wonderland

    1004 Number of Connected Subgraph

    1005 Seats

    1006 Football Games

    排序后判断前 i 个和不能少于 i*(i-1)/2 ,且总数为 n*(n-1)/2 即可。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int n;
     4 int b[20005];
     5 int main(){
     6     int t;
     7     while(cin>>t){
     8         while(t--){
     9             cin>>n;
    10             for(int i=1;i<=n;i++) cin>>b[i];
    11             int sum=0,flag=0;
    12             for(int i=1;i<=n;i++){
    13                 sum+=b[i];
    14                 if(sum<i*(i-1)) flag=1;
    15             }
    16             if(sum!=n*(n-1)) flag=1;
    17             if(flag==0) cout<<'T'<<endl;
    18             else cout<<'F'<<endl;
    19         }
    20     }
    21 
    22     return 0;
    23 }
    Psong

    1007 Friends and Enemies

    最多的情况为把所有人平均分成两组,然后内部互为敌人,外部互为朋友即可。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 long long n,m;
     4 int main(){
     5     while(cin>>n>>m){
     6         if(m>=(n-n/2)*(n/2)) cout<<"T"<<endl;
     7         else cout<<"F"<<endl;
     8     }
     9 
    10     return 0;
    11 }
    Psong

    1008 Function

    查询区间最左边的一个数向右取模后的结果,每次取模下降至少为一半,所以ST表打出最小值,然后对每个询问依次二分出向右的第一个比当前值小的位置。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int n,m;
     4 int a[100005];
     5 int dp[100005][35];
     6 int lg[100005];
     7 void RMQ_ST(int n){
     8     for(int i=1;i<=n;i++) lg[i]=(int)(log(1.0*i)/log(2.0));
     9     for(int i=1;i<=n;i++) dp[i][0]=a[i];
    10     for(int j=1;(1<<j)<=n;j++){
    11         for(int i=1;i<=n-(1<<j)+1;i++){
    12             dp[i][j]=min( dp[i][j-1],dp[i+(1<<(j-1))][j-1] );
    13         }
    14     }
    15 }
    16 int find_min(int l,int r){
    17     int k=lg[r-l+1];
    18     return min(dp[l][k],dp[r-(1<<k)+1][k]);
    19 }
    20 void solve(int l,int r){
    21     int res=a[l];
    22     int L=l+1,R=r;
    23     while(l<r){
    24         while(L<R){
    25             int mid=(L+R)/2;
    26             if(find_min(l+1,mid)<=res) R=mid;
    27             else L=mid+1;
    28         }
    29         if(find_min(l+1,L)>res) L=R;
    30         res%=a[L];
    31         L++; R=r;
    32         if(find_min(l+1,r)>res) break;
    33     }
    34     printf("%d
    ",res);
    35 }
    36 int main(){
    37     int t;
    38     scanf("%d",&t);
    39     while(t--){
    40         scanf("%d",&n);
    41         for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    42         RMQ_ST(n);
    43         scanf("%d",&m);
    44         while(m--){
    45             int l,r;
    46             scanf("%d%d",&l,&r);
    47             solve(l,r);
    48         }
    49     }
    50 
    51     return 0;
    52 }
    53 /*
    54 6
    55 18 30 15 8 6 4
    56 */
    Psong

    1009 Sparse Graph

    补图最短路,用两个set维护还没有记录的点,和与当前点相连的点。

    #include <bits/stdc++.h>
    using namespace std;
    vector<int> g[200005];
    int dis[200005];
    int n,m,s;
    int u,v;
    void bfs(){
        queue<int> q; q.push(s);
        set<int> s1,s2;
        for(int i=1;i<=n;i++)
            if(i!=s) s1.insert(i);
        while(!q.empty()){
            int u=q.front(); q.pop();
            for(int i=0;i<g[u].size();i++){
                int v=g[u][i];
                if(s1.find(v)!=s1.end()){
                    s1.erase(v);
                    s2.insert(v);
                }
            }
            set<int>::iterator it=s1.begin();
            for(;it!=s1.end();it++){
                dis[(*it)]=dis[u]+1;
                q.push(*it);
            }
            swap(s1,s2);
            s2.clear();
        }
        vector<int> ans;
        for(int i=1;i<=n;i++)
            if(i!=s) ans.push_back(dis[i]);
        for(int i=0;i<ans.size();i++){
            if(i==0) printf("%d",ans[i]);
            else printf(" %d",ans[i]);
        }
        printf("
    ");
    }
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&m);
            memset(dis,-1,sizeof(dis));
            for(int i=1;i<=n;i++) g[i].clear();
            for(int i=1;i<=m;i++) {
                scanf("%d%d",&u,&v);
                g[u].push_back(v);
                g[v].push_back(u);
            }
            scanf("%d",&s); dis[s]=0;
            bfs();
        }
    
        return 0;
    }
    /*
    2
    5 6
    1 2
    1 3
    2 4
    3 4
    2 5
    4 5
    2
    */
    Psong

    1010 Weak Pair

    离散化后dfs,用树状数组记录每个数出现个数,然后直接计数,当处理完一个点的时候要把这个这个值删除。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 LL n,k;
     5 LL root;
     6 LL a[100005];
     7 LL in[100005];
     8 vector<LL> g[100005];
     9 LL cnt;
    10 LL c[500005];
    11 LL lowbit(LL x){
    12     return x&(-x);
    13 }
    14 void add(LL pos,LL val){
    15     for(LL i=pos;i<=cnt;i+=lowbit(i)){
    16         c[i]+=val;
    17     }
    18 }
    19 LL sum(LL pos){
    20     LL res=0;
    21     for(LL i=pos;i>0;i-=lowbit(i)){
    22         res+=c[i];
    23     }
    24     return res;
    25 }
    26 vector<LL> v;
    27 LL getid(LL x){
    28     return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
    29 }
    30 
    31 LL ans;
    32 void dfs(LL u){
    33     LL id=getid(a[u]);
    34     if(a[u]){
    35         ans+=sum(getid(k/a[u]));
    36         add(id,1);
    37     }
    38     else{
    39         ans+=sum(cnt);
    40         add(1,1);
    41     }
    42     for(LL i=0;i<g[u].size();i++){
    43         dfs(g[u][i]);
    44     }
    45     if(a[u]) add(id,-1);
    46     else add(1,-1);
    47 }
    48 int main(){
    49     LL t;
    50     scanf("%lld",&t);
    51     while(t--){
    52         v.clear(); v.push_back(0);
    53         memset(c,0,sizeof(c));
    54         memset(in,0,sizeof(in));
    55         scanf("%lld%lld",&n,&k);
    56         for(LL i=1;i<=n;i++){
    57             g[i].clear();
    58             scanf("%lld",&a[i]);
    59             v.push_back(a[i]);
    60             if(a[i]!=0) v.push_back(k/a[i]);
    61         }
    62         for(LL i=1;i<n;i++){
    63             LL u,v;
    64             scanf("%lld%lld",&u,&v);
    65             g[u].push_back(v);
    66             in[v]++;
    67         }
    68         sort(v.begin(),v.end());
    69         v.erase(unique(v.begin(),v.end()),v.end());
    70         cnt=v.size(); ans=0;
    71         for(LL i=1;i<=n;i++){
    72             if(in[i]==0) root=i;
    73         }
    74         dfs(root);
    75         printf("%lld
    ",ans);
    76     }
    77 
    78 
    79     return 0;
    80 }
    Psong
  • 相关阅读:
    6、深入理解计算机系统笔记:存储器层次结构,存储技术(1)
    流程图【占无内容】
    程序的三种基本控制架构【只有提纲】
    Console算法[for]穷举法:百钱买百鸡
    Logic算法(狼羊白菜)
    Console算法continue与break的区别?
    Console算法[for]简单画图
    Console算法[for]输出等腰三角形
    Console算法[for]国王与老人的六十四格
    Console算法[for]素数
  • 原文地址:https://www.cnblogs.com/N-Psong/p/7141906.html
Copyright © 2011-2022 走看看