2017-2-24第二周周赛题解

A题:Morning_X和数独

题目大意就是

给你一个数独,让你填数:

1.每行的九个数字互不相同;

2.每列的九个数字各不相同;

3.被分成的3*3的小矩阵中的九个数字互不相同;

输出完成后的数表,若不能满足上述条件,则输出原图。

其实就是一个DFS,不断的DFS,失败了就回溯。

分别用三个数组来标记标记在第i行中是否出现了数字x,标记在第j列中是否出现了数字y,第k个3*3子格中是否出现了数字z

前两个数组都比较好处理,主要是找出子网格的序号与行i列j的关系

关系玩过数独的只要稍微推导一下就可以知道关系的数学式为 3*((i-1)/3)+(j-1)/3+1=k

这样我们就可以记录k个3*3子格中数字z是否出现了:

AC代码如下:

 1 #include<stdio.h>
 2 #include<string.h>
 3 int a[10][10];
 4 int c[10][10];
 5 int map[10][10];
 6 int s[10][10];
 7 int f(int x,int y)
 8 {
 9     return 3*((x-1)/3)+(y-1)/3+1;
10 }
11 void init()
12 {
13     int i,j;
14     char ch;
15     memset(a,0,sizeof(a));
16     memset(c,0,sizeof(c));
17     memset(s,0,sizeof(s));
18     for(i=1; i<=9; i++)
19         {
20             for(j=1; j<=9; j++)
21             {
22                 scanf("%c",&ch);
23                 map[i][j]=ch-'0';
24                 if(map[i][j])
25                 {
26                     int k;
27                     k=f(i,j);
28                     a[i][map[i][j]]=1;
29                     c[j][map[i][j]]=1;
30                     s[k][map[i][j]]=1;
31                 }
32             }
33             getchar();
34         }
35 }
36 int DFS(int x,int y)
37 {
38     if(x==10)
39         return 1;
40     int flag=0;
41     if(map[x][y])
42     {
43         if(y==9)
44             flag=DFS(x+1,1);
45         else
46             flag=DFS(x,y+1);
47         if(flag)
48             return 1;
49         else
50             return 0;
51     }
52     else
53     {
54         int k=f(x,y);
55         for(int i=1; i<=9; i++)
56             if(!a[x][i] && !c[y][i] && !s[k][i])
57             {
58                 map[x][y]=i;
59                 a[x][i]=1;
60                 c[y][i]=1;
61                 s[k][i]=1;
62                 if(y==9)
63                     flag=DFS(x+1,1);
64                 else
65                     flag=DFS(x,y+1);
66                 if(!flag)
67                 {
68                     map[x][y]=0;
69                     a[x][i]=0;
70                     c[y][i]=0;
71                     s[k][i]=0;
72                 }
73                 else
74                     return 1;
75             }
76     }
77     return 0;
78 }
79 int main()
80 {
81     int t;
82     scanf("%d",&t);
83     getchar();
84     while(t--)
85     {
86         init();
87         DFS(1,1);
88         for(int i=1; i<=9; i++)
89         {
90             for(int j=1; j<=9; j++)
91                 printf("%d",map[i][j]);
92             printf("
");
93         }
94     }
95     return 0;
96 }
View Code

B题:Morning_X和seventh的字符串

这是一道水题,

比较两个字符串是否相等嘛,如果相等就输出-1,否则输出较长的那个字符串长度,可以直接用strcmp进行比较,不过我为了保险就一个一个比较了

AC代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 int main()
 6 {
 7     char a[100005],b[100005];
 8     while(~scanf("%s%s",&a,&b))
 9     {
10         int len1=strlen(a),len2=strlen(b);
11         int flag=0;
12         if(len1!=len2)
13             flag=1;
14         for(int i=0;i<len1;i++)
15             if(a[i]!=b[i])
16             flag=1;
17         if(flag==1)
18             printf("%d
",max(len1,len2));
19         else
20             printf("-1
");
21     }
22     return 0;
23 }
View Code

C题:Morning_X的小学数学

题意就是求n的第K个约数;

又是一道水题;

思路其实就是:首先可以求得小于等于根号n的约数,如果k比较小的话直接输出就可以了

而其他约数均为n/小于根号n的约数,所以数量为2倍。对于根号n为整数的再做个特判就可以了。

AC代码:

 1 #include<stdio.h>
 2 #include<vector>
 3 using namespace std;
 4 vector <int> x;
 5 int main()
 6 {
 7     long long n;
 8     int k;
 9     scanf("%I64d%d",&n,&k);
10     for(long long  i=1;i*i<=n;i++)
11             if(n%i==0)
12                 x.push_back(i);
13             if(x.size()>=k)
14                 printf("%d",x[k-1]);
15             else
16             {
17                 int a=x.size(),s=(long long)x[a-1]*x[a-1]==n;
18                 if(k>a*2-s)
19                     printf("-1");
20                 else
21                     printf("%I64d",n/(long long)x[2*a-k-s]);
22             }
23     return 0;
24 }
View Code

D题:Morning_X的苹果

这一题的题意其实挺坑的,我题面写的最久的就是这道题;

题意大概就是

Morning_X很喜欢吃苹果,每天会吃K个,如果不足K个,就会将所有拥有的都吃了。

不傻的人都知道,苹果过期了之后肯定就不能吃了,那就只能扔掉。(鬼知道为什么会过期)

现在冰箱中有N个苹果,超市中有M个苹果,如果冰箱中的苹果吃不完就有浪费的情况出现,输出-1,否则输出能够在超市中购买的苹果数量的最大值。

并且输出可以购买的苹果的编号。

这一题还是不要看我的题解比较好,因为我是暴力过的,第一次在OJ上交还超时了,我是卡时间过的233;

准确的思路是二分加贪心,而我的是二分加暴力处理

思路:首先我们将冰箱中的苹果按照到期时间按照从小到大排序,很明显的就是说我们希望先吃到期时间早的,才能更好的避免浪费。

接下来O(n)暴力判断一下这些苹果是否都能吃完,如果能,继续进行,否则输出-1.

接下来我们按照到期时间从大到小排序,我们希望购买的苹果肯定是越晚到期越好。

接下来考虑到这样一点:购买的苹果越多,越有可能要浪费掉,所以我们知道这里有一个单调性,我们考虑二分购买的苹果数量。

对于二分出来的中间值mid,我们暴力处理一次判断能否将这N+mid个苹果都吃完,如果可以,增加购买数量,否则减少购买数量。

过程维护最后一次可行方案数,然后再输出

AC代码如下:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 struct node
 6 {
 7     int date,pos;
 8 }b[1000700];
 9 int a[1000700];
10 int c[2007000];
11 int output[2000700];
12 
13 int n,m,k;
14 int cmp(node a,node b)
15 {
16     return a.date>b.date;
17 }
18 int judge(int a[],int n)
19 {
20     int day=0;
21     int cnt=0;
22     for(int i=0;i<n;i++)
23     {
24         if(day>a[i])return 0;
25         cnt++;
26         if(cnt==k)
27         {
28             cnt=0;
29             day++;
30         }
31     }
32     return 1;
33 }
34 int Slove(int mid)
35 {
36     int tot=0;
37     for(int i=0;i<n;i++)c[tot++]=a[i];
38     for(int i=0;i<=mid;i++)c[tot++]=b[i].date;
39     sort(c,c+tot);
40     if(judge(c,tot)==1)
41     {
42         for(int i=0;i<=mid;i++)
43         {
44             output[i]=b[i].pos;
45         }
46         return 1;
47     }
48     else return 0;
49 }
50 int main()
51 {
52     while(~scanf("%d%d%d",&n,&m,&k))
53     {
54         for(int i=0;i<n;i++)scanf("%d",&a[i]);
55         for(int i=0;i<m;i++)scanf("%d",&b[i].date),b[i].pos=i+1;
56         sort(a,a+n);sort(b,b+m,cmp);
57         if(judge(a,n)==0)
58         {
59             printf("-1
");
60             continue;
61         }
62         int ans=-1;
63         int l=0;
64         int r=m-1;
65         while(r-l>=0)
66         {
67             int mid=(l+r)/2;
68             if(Slove(mid)==1)
69             {
70                 l=mid+1;
71                 ans=mid;
72             }
73             else
74             {
75                 r=mid-1;
76             }
77         }
78         printf("%d
",ans+1);
79         for(int i=0;i<ans+1;i++)
80         {
81             printf("%d ",output[i]);
82         }
83         printf("
");
84     }
85 }
View Code

E题:Morning_X的数论

这道题的题意不知道有多少人看得懂233,其实很坑的,我完全不知道怎么翻译,所以我就生硬的搬了原来CF上面的题目

这道题比较适合Home_W做233,不是算法题,是智商题,完全就是考脑洞,所以我题目就提醒了这题是数论题

题目的意思就是:

是否有一个等差数列x,x+d,..,x+(n-1)*d,使得其每个元素对m取模后,结果为a1,a2,..,an。如果有,输出首项x和公差d。如果没有,输出-1。多解输出一个即可。

思路就是:枚举d和a1,来验证所求数列是否满足题意.

然后在用到两个等差数列的公式:

1、a1=(sn-n*(n-1)/2*d)/n

2、Sn^2=n(a1)^2+n(n-1)(2n-1)d^2/6+n(n-1)*d*a1

在用第一个公式的时候因为涉及到除法取模,所以我们得求一下逆元(代码中fp函数的作用)

AC代码如下:

 1 #include<stdio.h>
 2 #include<algorithm>
 3 using namespace std;
 4 const int MAXN=100005;
 5 int a[MAXN],b[MAXN];
 6 int fp(int a,int k,int m)
 7 {
 8     int res=1;
 9     while(k)
10     {
11         if(k&1)res=1LL*res*a%m;
12         a=1LL*a*a%m;
13         k>>=1;
14     }
15     return res;
16 }
17 int main()
18 {
19     int m,n;
20     scanf("%d%d",&m,&n);
21     int s[2]={0,0};
22     for(int i=1;i<=n;i++)
23     {
24         scanf("%d",&a[i]);
25         s[0]=(s[0]+a[i])%m;
26         s[1]=(s[1]+1LL*a[i]*a[i])%m;
27     }
28     if(n==1)return 0*printf("%d 0",a[1]);
29     if(n==m)return 0*printf("0 1");
30     sort(a+1,a+n+1);
31     for(int i=2;i<=n;i++)
32     {
33         int d=(a[i]-a[1]+m)%m;
34         int x=1LL*(s[0]-1LL*n*(n-1)/2%m*d%m+m)*fp(n,m-2,m)%m;//a1=(sn-n*(n-1)/2*d)/n;
35         //Sn=n(a1)^2+n(n-1)(2n-1)d^2/6+n(n-1)*d*a1
36         int temp=1LL*n*x%m*x%m;
37         temp=(temp+1LL*n*(n-1)%m*d%m*x%m)%m;
38         temp=(temp+1LL*n*(n-1)*(2*n-1)/6%m*d%m*d%m)%m;
39         if(temp==s[1])
40         {
41             b[1]=x;
42             for(int i=2;i<=n;i++)
43                 b[i]=(b[i-1]+d)%m;
44             sort(b+1,b+n+1);
45             bool isok=1;
46             for(int i=1;i<=n;i++)
47                 isok&=(a[i]==b[i]);
48             if(isok)return 0*printf("%d %d",x,d);
49         }
50     }
51     return 0*printf("-1");
52 }
View Code
原文地址:https://www.cnblogs.com/tijie/p/6435175.html