前言
WF试题册还是相当美观工整的,很赏心悦目。
昨天到今天上午,总共写出来三道题。第一题是自己写出来的,后两题是看cf上题解自己摸索的。
题解
Y题
题意看上去有点像模拟一个消数的过程。我仔细一想,结果无外乎几种可能
0 1 01 10 010 101
所以,首先消除连续的1和0串,变成1,0,101010,0101010等等这种。
例如11000110001,消除连续串之后变成10101.
然后,根据这个串,长度为1直接输出;否则能消除则直接消除后面的若干的01或10串,使长度变成最终的2或3.
例如,上述例子变成101.
标程
#include <iostream>
using namespace std;
#include <set>
#include <algorithm>
#include <cmath>
#include <map>
#include <cstdio>
#include <string>
#include <cstring>
#include <string.h>
#include <stdlib.h>
#include <iomanip>
#include <fstream>
#include <stdio.h>
#include <stack>
#include <queue>
#include <ctype.h>
#include <vector>
#include <random>
#include <bitset>
#define ll long long
#define ull unsigned long long
#define pb push_back
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define pii pair<int, int>
#define pli pair<ll, int>
#define pil pair<int, ll>
#define pll pair<ll, ll>
#define endl '\n'
const double pai = acos(-1);
ll extend_gcd(ll a, ll b, ll &x, ll &y)
{
if (b == 0)
{
x = 1;
y = 0;
return a;
}
ll d = extend_gcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
ll fastpow(ll a, ll n, ll mod)
{
ll ans = 1;
a %= mod;
while (n)
{
if (n & 1)
ans = (ans * a) % mod; //% mod
a = (a * a) % mod; //% mod
n >>= 1;
}
return ans;
}
int dir[4][2] =
{
{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; // d a w s
const ll inf = 1000000000000000000ll;
const ll mod = 1e9 + 7, P1 = 13331;
const double eps = 1e-7;
const int N = 1e5 + 10, M = 1e4 + 10;
string s;
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//freopen("ain.txt", "r", stdin);freopen("aout.txt", "w", stdout);
cin>>s;
int len=s.size();
string ans="";
ans=ans+s[0];
rep(i,1,len-1)
{
int len=ans.size();
if(s[i]!=ans[len-1])
{
ans=ans+s[i];
}
}
if(ans.size()==1)
{
cout<<ans;
}
else
{
if(ans.size()%2==1)
{
cout<<ans[0]<<ans[1]<<ans[2];
}
else
{
cout<<ans[0]<<ans[1];
}
}
return 0;
}
W题
这个题我是想了好多方法都没想出来,始终感觉差一步,后来看了题解,
1 0 0
0 1 0
0 0 1
1 1 1
1 2 3
这样构造问法,甚是巧妙。这五个问无论哪一问撒谎,剩余四问都能自证是对的。
设第i问的回答的数字为a[i]
假设第五问撒谎,则前四问都没撒谎,a[1]+a[2]+a[3]==a[4]
假设第四问撒谎,a[1]+2*a[2]+3*a[3]==a[5]
假设第一问撒谎,则ans[1]=a[5]-2*a[2]-3*a[3],带入第四个式子,如果ans[1]+a[2]+a[3]==a[4],则可解得答案为ans[1],a[2],a[3]
标程
#include <iostream>
using namespace std;
#include <set>
#include <algorithm>
#include <cmath>
#include <map>
#include <cstdio>
#include <string>
#include <cstring>
#include <string.h>
#include <stdlib.h>
#include <iomanip>
#include <fstream>
#include <stdio.h>
#include <stack>
#include <queue>
#include <ctype.h>
#include <vector>
#include <random>
#include <bitset>
#define ll long long
#define ull unsigned long long
#define pb push_back
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define pii pair<int, int>
#define pli pair<ll, int>
#define pil pair<int, ll>
#define pll pair<ll, ll>
//#define endl '\n'
const double pai = acos(-1);
ll extend_gcd(ll a, ll b, ll &x, ll &y)
{
if (b == 0)
{
x = 1;
y = 0;
return a;
}
ll d = extend_gcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
ll fastpow(ll a, ll n, ll mod)
{
ll ans = 1;
a %= mod;
while (n)
{
if (n & 1)
ans = (ans * a) % mod; //% mod
a = (a * a) % mod; //% mod
n >>= 1;
}
return ans;
}
int dir[4][2] =
{
{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; // d a w s
const ll inf = 1000000000000000000ll;
const ll mod = 1e9 + 7, P1 = 13331;
const double eps = 1e-7;
const int N = 1e5 + 10, M = 1e4 + 10;
int a[10];
int main()
{
//ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//freopen("ain.txt", "r", stdin);freopen("aout.txt", "w", stdout);
cout<<"1 0 0"<<endl;
cin>>a[1];
cout<<"0 1 0"<<endl;
cin>>a[2];
cout<<"0 0 1"<<endl;
cin>>a[3];
cout<<"1 1 1"<<endl;
cin>>a[4];
cout<<"1 2 3"<<endl;
cin>>a[5];
if(a[1]+a[2]+a[3]==a[4])
{
cout<<a[1]<<" "<<a[2]<<" "<<a[3]<<endl;
exit(0);
}
int tem=a[4]-a[2]-a[3];
if(tem+2*a[2]+3*a[3]==a[5])
{
cout<<tem<<" "<<a[2]<<" "<<a[3]<<endl;
exit(0);
}
tem=a[4]-a[1]-a[3];
if(a[1]+2*tem+3*a[3]==a[5])
{
cout<<a[1]<<" "<<tem<<" "<<a[3]<<endl;
exit(0);
}
tem=a[4]-a[1]-a[2];
if(a[1]+2*a[2]+3*tem==a[5])
{
cout<<a[1]<<" "<<a[2]<<" "<<tem<<endl;
exit(0);
}
cout<<a[1]<<" "<<a[2]<<" "<<a[3]<<endl;
return 0;
}
P题
今天早上做的一道题,一开始觉得可能是解方程组,高斯消元,但一看数据范围不对。后来已经看出来考察图论,联通分量,有点像拓扑排序,但又感觉无从下手。不知道怎么写这个复杂的程序。
建模:简单来说,对于第i个灯,c[i]记录这个灯颜色对应的数字,red c[i]=0,green c[i]=1,blue c[i]=2。
对于每一个按钮,无外乎三种可能,开0或1或2次。因为这个题是对3取模。
那么怎么写程序呢。
我的方法是遍历所有的灯,若这个灯没有按钮控制,看它颜色,不是红色直接impossible。
若只有一个按钮控制,那么这个按钮按几次是确定的,设这是第i个按钮,ding[i]记录它按几次。
然后考虑这个按钮影响到的其他的灯,假设影响到了j灯,倘若j灯只被第i个按钮所控制,那么看看(c[j]+ding[i])%3是否为0 ,为0 则正确,否则impossible。
倘若j灯被两个按钮控制,那么i按钮按几次定了,另一个按钮按几次也能定下来,根据初始颜色和i按钮按几次。再把这个按钮影响到的灯都这样考察一遍。
这是个复杂的过程。
结束后,这些灯vis标记为1,后续遍历时不再考虑。
倘若遍历时一个灯被两个按钮控制,那么比较复杂,枚举,这两个灯颜色有三种可能,都枚举一遍,过程同上。若三种可能都最终导致impossible,那么输出impossible。这三种情况可行的情况计算按按钮的次数的最小值,加在ans上。
标程
#include <iostream>
using namespace std;
#include <set>
#include <algorithm>
#include <cmath>
#include <map>
#include <cstdio>
#include <string>
#include <cstring>
#include <string.h>
#include <stdlib.h>
#include <iomanip>
#include <fstream>
#include <stdio.h>
#include <stack>
#include <queue>
#include <ctype.h>
#include <vector>
#include <random>
#include <bitset>
#define ll long long
#define ull unsigned long long
#define pb push_back
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define pii pair<int, int>
#define pli pair<ll, int>
#define pil pair<int, ll>
#define pll pair<ll, ll>
// #define endl '\n'
const double pai = acos(-1);
ll extend_gcd(ll a, ll b, ll &x, ll &y)
{
if (b == 0)
{
x = 1;
y = 0;
return a;
}
ll d = extend_gcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
ll fastpow(ll a, ll n, ll mod)
{
ll ans = 1;
a %= mod;
while (n)
{
if (n & 1)
ans = (ans * a) % mod; //% mod
a = (a * a) % mod; //% mod
n >>= 1;
}
return ans;
}
int dir[4][2] =
{
{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; // d a w s
const ll inf = 1000000000000000000ll;
const ll mod = 1e9 + 7, P1 = 13331;
const double eps = 1e-7;
const int N = 4e5 + 10, M = 1e4 + 10;
int l, b;
string s;
int c[N];
int x[N][3];
int ans;
bool vis[N];
vector<int> ying[N];
struct node
{
int id, add;
node(int a, int b)
{
id = a;
add = b;
}
};
int ding[N]; // jilu mouyige deng shifou dingle
void cuo()
{
cout << "impossible";
exit(0);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// freopen("ain.txt", "r", stdin);
// freopen("aout.txt", "w", stdout);
cin >> l >> b;
cin >> s;
s = ' ' + s;
rep(i, 1, l)
{
if (s[i] == 'R')
{
c[i] = 0;
}
else if (s[i] == 'G')
{
c[i] = 1;
}
else
{
c[i] = 2;
}
}
rep(i, 1, b)
{
ding[i] = -1;
int k;
cin >> k;
rep(j, 1, k)
{
int temp;
cin >> temp;
ying[i].pb(temp);
if (x[temp][1])
{
x[temp][2] = i;
}
else
{
x[temp][1] = i;
}
}
}
rep(i, 1, l)
{
if (vis[i]) // zhege dian meikaolv guo
{
continue;
}
if (x[i][1] == 0)
{
if (c[i])
{
cuo();
}
}
else if (x[i][2] == 0)
{
rep(jj, 0, 2)
{
if ((c[i] + jj) % 3 == 0)
{
ding[x[i][1]] = jj;
ans += jj;
break;
}
}
queue<int> q;
for (auto j : ying[x[i][1]])
{
q.push(j);
}
//
// cout<<x[1][1]<<" "<<ding[x[1][1]]<<endl;
while (q.size())
{
int u = q.front();
vis[u] = 1;
//
// cout<<i<<" "<<u<<endl;
q.pop();
if (x[u][2] == 0)
{
if ((c[u] + ding[x[u][1]]) % 3 == 0)
{
continue;
}
else
{
cuo();
}
}
if (x[u][2])
{
if (ding[x[u][1]] > -1 && ding[x[u][2]] > -1)
{
if ((c[u] + ding[x[u][1]] + ding[x[u][2]]) % 3 == 0)
{
continue;
}
cuo();
}
if (ding[x[u][1]]>-1)
{
rep(j, 0, 2)
{
if ((c[u] + ding[x[u][1]] + j) % 3 == 0)
{
ding[x[u][2]] = j;
ans += j;
for (auto jj : ying[x[u][2]])
{
q.push(jj);
}
}
}
}
else
{
rep(j, 0, 2)
{
if ((c[u] + ding[x[u][2]] + j) % 3 == 0)
{
ding[x[u][1]] = j;
ans += j;
for (auto jj : ying[x[u][1]])
{
q.push(jj);
}
}
}
}
}
}
}
else if (x[i][2])
{
ll temp=inf;
rep(jj, 0, 2)
{
ll tem=0;
queue<int > qing;
ding[x[i][1]] = jj;
qing.push(x[i][1]);
qing.push(x[i][2]);
tem += jj;
rep(jjj,0,2)
{
if((c[i]+jj+jjj)%3==0)
{
ding[x[i][2]]=jjj;
tem+=jjj;
}
}
queue<int> q;
for (auto j : ying[x[i][1]])
{
q.push(j);
}
for(auto j:ying[x[i][2]])
{
q.push(j);
}
while (q.size())
{
int u = q.front();
vis[u] = 1;
//
// cout<<i<<" "<<u<<endl;
q.pop();
if (x[u][2] == 0)
{
if ((c[u] + ding[x[u][1]]) % 3 == 0)
{
continue;
}
else
{
goto tt;
}
}
if (x[u][2])
{
if (ding[x[u][1]] > -1 && ding[x[u][2]] > -1)
{
if ((c[u] + ding[x[u][1]] + ding[x[u][2]]) % 3 == 0)
{
continue;
}
goto tt;
}
if (ding[x[u][1]]>-1)
{
rep(j, 0, 2)
{
if ((c[u] + ding[x[u][1]] + j) % 3 == 0)
{
ding[x[u][2]] = j;
qing.push(x[u][2]);
tem += j;
for (auto jj : ying[x[u][2]])
{
q.push(jj);
}
}
}
}
else
{
rep(j, 0, 2)
{
if ((c[u] + ding[x[u][2]] + j) % 3 == 0)
{
ding[x[u][1]] = j;
qing.push(x[u][1]);
tem += j;
for (auto jj : ying[x[u][1]])
{
q.push(jj);
}
}
}
}
}
}
temp=min(temp,tem);
tt:
while(qing.size())
{
int u=qing.front();
ding[u]=-1;
qing.pop();
}
}
if(temp==inf)
{
cuo();
}
ans+=temp;
}
}
cout << ans;
return 0;
}
谢谢