一、整体流程

做了A和B。

大胆猜想,直接写码……

二、具体题目

A. Windblume Ode

(1)读题

①场上:从样例解释中发现,输出时的顺序无关紧要,换句话讲,输出1 2 3 ... 8 9与输出6 9 1 2 3 ... 8都算正确。

题目要求集合大小尽量大,但不需要总值最大。同时,需要判断合数或者素数。

那么,如果保证是合数的话,就可以直接输出;如果是素数的话,可以想办法减为合数。

②改进:可以大胆猜想算法。一般对于最简单的一道题,都有着非常容易写出的代码,即不考察算法和码力,转而考虑数学猜想和证明能力。对于此题,大胆猜想可随意删除一个数字,如果保证删除此数后新的和为合数,就贪心的输出答案。

③证明:在和本身为合数的情况下,直接输出答案。如果本身不是合数,那么和一定是质数,也一定是奇数。既然和是奇数,那么只要再减去一个奇数就可以变成偶数了,既然是偶数,那么也必然是合数。考虑到和为奇数,那么一定有起码一个奇数,即充分性。

(2)做题

由于int sum=0;定义在了函数外,wa了两次。

素数筛

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
bool isGood[300000];//�Ƿ�Ϊ���� 

void init(){
    for(int i=2;i<=20000;i++){
        for(int j=2;j<=20000;j++){
            if(i*j>20000)continue;
            else isGood[i*j]=1;
        }
    }
} 

int a[200];
int main()
{
    //cout<<Miller_Rabin(3)<<endl;
    init();
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        int sum=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            sum+=a[i];
        }
        //printf("isGood[%d]=%d\n",sum,isGood[sum]);
        if(isGood[sum]){//�����Ǻ��� 
            printf("%d\n",n);
            for(int i=1;i<=n;i++){
                printf("%d ",i);
            } 
            printf("\n");
        }else{//�����Ǻ��� 
            //ȥ��һ������ʹ��ȥ�����sumΪ������Ȼ������� 
            int removeIndex=0;
            for(int i=1;i<=n;i++){
                if(isGood[sum-a[i]]){
                    removeIndex=i;
                    //printf("removeIndex:%d\n",removeIndex);
                    break;
                }
            }
            printf("%d\n",n-1);
            for(int i=1;i<=n;i++){
                if(i!=removeIndex){
                    printf("%d ",i);
                }
            }
            printf("\n");
        }
    }
    return 0;
}
View Code

Miller-Rabin

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int prime[10]={2,3,5,7,11,13,17,19,23,29};
int Quick_Multiply(int a,int b,int c)  
{
    long long ans=0,res=a;
    while(b)
    {
        if(b&1)
          ans=(ans+res)%c;
        res=(res+res)%c;
        b>>=1;
    }
    return (int)ans;
}
int Quick_Power(int a,int b,int c)   
{
    int ans=1,res=a;
    while(b)
    {
        if(b&1)
          ans=Quick_Multiply(ans,res,c);
        res=Quick_Multiply(res,res,c);
        b>>=1;
    }
    return ans;
}
bool Miller_Rabin(int x)  
{
    int i,j,k;
    int s=0,t=x-1;
    if(x==2)  return true; 
    if(x<2||!(x&1))  return false;  
    while(!(t&1))
    {
        s++;
        t>>=1;
    }
    for(i=0;i<10&&prime[i]<x;++i)     
    {
        int a=prime[i];
        int b=Quick_Power(a,t,x);  
        for(j=1;j<=s;++j)   
        {
            k=Quick_Multiply(b,b,x); 
            if(k==1&&b!=1&&b!=x-1)   
              return false;
            b=k;
        }
        if(b!=1)  return false;  
    }
    return true; 
}
 
 
int a[200];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        int sum=0;
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            sum+=a[i];
        }
        if(!Miller_Rabin(sum)){//?????????? 
            printf("%d\n",n);
            for(int i=1;i<=n;i++){
                printf("%d ",i);
            } 
            printf("\n");
        }else{
            //???????????????????sum??????????????? 
            int removeIndex=0;
            for(int i=1;i<=n;i++){
                if(!Miller_Rabin(sum-a[i])){
                    removeIndex=i;
                    //printf("removeIndex:%d\n",removeIndex);
                    break;
                }
            }
            printf("%d\n",n-1);
            for(int i=1;i<=n;i++){
                if(i!=removeIndex){
                    printf("%d ",i);
                }
            }
            printf("\n");
        }
    }
    return 0;
}
View Code

B. Omkar and Heavenly Tree

 

 

(1)读题

①场上:题意要求两点之间的简单路径中不能有违法点,考虑重新建图。注意到两点之间如果有任何限制,那么连接这两个点,就可以直接忽略掉这些限制。但是如果直接连接输出答案的话,可能出现环或者其他构造答案,因此要换一种连点越过限制的方法。

②改进:div2的B题一般不会太难,难度主要在思维上。重新审视要求,发现对于树的类型和形状没有确切的规定,输出答案十分自由。那么联想到"菊花图"

③证明:菊花图有着一个特性:任意两点之间的中间点必然有且只有中心点和两点上面的点。联合a,b,c均独特的特性,得到正解为构造一颗深度为2的菊花图.

(2)做题

#include<cstdio>
#include<iostream>
using namespace std;
bool baned[200000];
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m;
        scanf("%d%d",&n,&m); 
        for(int i=1;i<=n;i++)baned[i]=0;
        for(int i=1;i<=m;i++){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            baned[b]=1;
        }
        for(int i=1;i<=n;i++){
            if(!baned[i]){//
                for(int j=1;j<=n;j++){
                    if(j!=i)
                    printf("%d %d\n",i,j);
                }
                break; 
            }
        }
    }
    return 0;
}
View Code