2018acm区域赛青岛

zoj4060

思维题目+找规律,比较难想!

划分不同块,找不同块。

根据不同块的数目又分为4种情况。(划分块就够难想了,这4种情况计算规律更是难找!)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 typedef long long ll;
 6 ll n;
 7 string s,t;
 8 
 9 int main()
10 {
11     ios::sync_with_stdio(0); cin.tie(0);
12     
13     int T;
14     cin>>T;
15     while(T--)
16     {
17         cin>>n>>s>>t;
18         int cnt=0;
19         for(int i=0;i<n;i++)
20         {   //i=0是有单个字符这种特殊情况
21             if((i==0 || s[i-1]==t[i-1]) && s[i]!=t[i]) cnt++;
22         }
23         
24         if(cnt>2) cout<<"0"<<endl;
25         else if(cnt==2) cout<<"6"<<endl;
26         else if(cnt==1) cout<<ll(2*n-2)<<endl;
27         else cout<<ll(n*(n+1)/2)<<endl;
28     }
29 }

Plants vs. Zombieszoj4062

最小值最大化,典型的二分答案

关键是judge函数怎么写

除此之外,写出judge也很难ac,此题尽是坑点,写的我一把辛酸泪啊QAQ~~

什么最后一个要特判,不加次数。。

什么很容易超ll。。

什么负数。。

什么超时。。

都要及时跳出才行

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=1e5+10;
 7 
 8 int n;
 9 ll m;
10 ll a[maxn],d[maxn];
11 
12 ll judge(ll k)
13 {
14     //memset(d,0,(n+1)*sizeof(ll));
15     //memset(d,0,sizeof(d));//1520ms
16     for(int i=0;i<=n+1;i++) d[i]=0;//630ms
17     
18     ll cnt=0;
19     for(int i=1;i<=n;i++)
20     {
21         if(i==n && d[i]>=k) break;//坑点1,最后一个特判
22         
23         cnt++; d[i]+=a[i];//注意这个细节,d[i]+=a[i]要放到continue前面,后面必错!(先把每一步必须的一步加上,不要和后面的放在一起算,不容易错)
24         if(d[i]>=k) continue;//坑点2,不要一直加,会超ll,同时关键防止了下面负数情况!!
25         //d[i]+=a[i];//之前以为放这一直错QAQ
26         
27         ll c=(k-d[i])/a[i];//坑点3,这里(通过上面continue)要防止了过大变负数
28         if((k-d[i])%a[i]) c++;
29         cnt+=2*c;
30         d[i]+=c*a[i];
31         d[i+1]+=c*a[i+1];
32         
33         if(cnt>m) break;
34     }
35     return cnt;
36 }
37 
38 int main()
39 {
40     ios::sync_with_stdio(0);
41     cin.tie(0);
42 
43     int T;
44     cin>>T;
45     while(T--)
46     {
47         cin>>n>>m;
48         ll mn=1e5+10;
49         for(int i=1;i<=n;i++) cin>>a[i], mn=min(mn,a[i]);
50 
51         ll l=0, r=mn*m,ans=0;
52         while(l<=r)
53         {
54             ll mid=(l+r)>>1;
55             if(judge(mid)<=m) 
56             {
57                 ans=mid;
58                 l=mid+1;
59             }
60             else r=mid-1;
61         }
62         cout<<ans<<endl;
63     }
64 }

Books,zoj4067

略难的贪心,分清楚3种情况即可(况且样例都给你了,解释的清清楚楚名明明白白QAQ) 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 typedef long long ll;
 6 const ll maxn=1e5+10;
 7 const ll inf=1e9+5;
 8 ll T,n,m;
 9 ll a[maxn];
10 
11 int main()
12 {
13     ios::sync_with_stdio(0); cin.tie(0);
14 
15     cin>>T;
16     while(T--)
17     {
18         cin>>n>>m;
19         ll cnt0=0;
20         for(int i=1;i<=n;i++)
21         {
22             cin>>a[i];
23             if(a[i]==0) cnt0++;
24         }
25 
26         if(m>=n) cout<<"Richman"<<endl;
27         else if(cnt0>m) cout<<"Impossible"<<endl;
28         else
29         {
30             m-=cnt0;//贪心肯定先选m为0的书籍
31             ll mn=inf,ans=0;
32             for(int i=1;i<=n;i++)
33             {
34                 if(a[i]==0) continue;//因为为0的书籍已经挑过了,前面m-=cnt0!
35 
36                 if(m)//如果还有次数的话就选
37                 {
38                     ans+=a[i];
39                     m--;
40                 }
41                 else mn=min(mn,a[i]);//从没选过的剩下的里面选一个最小的
42             }
43 
44             ans+=mn-1;
45             cout<<ans<<endl;
46         }
47     }
48 
49     return 0;
50 }

Function and Function,zoj4070

签到题,给你的递归形式,但不要一条路到死。递归可以改循环,循环也可以改递归,哪个不爆栈方便用哪个。

做这题有2点:

1.做这题关键重点:把它的函数嵌套全部展开,g(x)就变成了次方个f(x)!!从头开始计算就行了。

2.然后是规律,k辣么大每次都算肯定超市啦,发现0和1的函数值相反正好来回跳,所以到0我们就可以根据剩余次方判断出答案啦!

(3.有个坑点很容易错,0的函数值是0,必须特判返回1。像其它一样取位正常算的话返回是0。很容易错)

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 typedef long long ll;
 5 ll s[10]={1,0,0,0,1,0,1,0,2,1};
 6 ll T,x,k;
 7 
 8 ll f(ll y)
 9 {
10     if(y==0) return 1;//坑点,很重要,因为0特殊,下面返回0是错的!
11 
12     ll ans=0;
13     while(y)
14     {
15         ans+=s[y%10];
16         y/=10;
17     }
18 
19     return ans;
20 }
21 
22 int main()
23 {
24     //ios::sync_with_stdio(false); cin.tie(0);
25 
26     scanf("%lld",&T);
27     while(T--)
28     {
29         scanf("%lld%lld",&x,&k);
30 
31         if(k==0) { printf("%lld
",x); continue;}
32 
33         for(int i=1;i<=k;i++)
34         {
35             x=f(x);
36             if(x==0)
37             {
38                 ll t=k-i;
39                 if(t%2) x=1;
40                 else x=0;
41                 break;
42             }
43         }
44         printf("%lld
",x);
45     }
46 
47     return 0;
48 }

完。

原文地址:https://www.cnblogs.com/redblackk/p/9999184.html